2013年9月2日 星期一

PHP Extension (1) - 環境準備與Hello World

下列所有實作均以Ubuntu為範例,視不同distribution或版本可能指令與路徑均有不同

準備環境

$sudo apt-get install apache2 php5 php5-dev

Hello World

傳統PHP function要達到輸出hello world的方式
<?php
function hello_world() {  
  return 'Hello World';  
}
echo hello_world();
?>

若要使用PHP extension開發,要使用c語言實作出相同的function

test_hello_world.h
#ifndef PHP_TEST_HELLO_WORLD_H  
#define PHP_TEST_HELLO_WORLD_H  

extern zend_module_entry test_hello_world_module_entry;  
#define phpext_test_hello_world_ptr &test_hello_world_module_entry  

#ifdef PHP_WIN32  
#define PHP_TEST_HELLO_WORLD_API __declspec(dllexport)  
#else  
#define PHP_TEST_HELLO_WORLD_API  
#endif  

#ifdef ZTS  
#include "TSRM.h"  
#endif  

PHP_MINIT_FUNCTION(test_hello_world);  
PHP_MSHUTDOWN_FUNCTION(test_hello_world);  
PHP_MINFO_FUNCTION(test_hello_world);  

PHP_FUNCTION(hello_world);  

/*  
    Declare any global variables you may need between the BEGIN 
    and END macros here:      

    ZEND_BEGIN_MODULE_GLOBALS(test_hello_world) 
    long  global_value; 
    char *global_string; 
    ZEND_END_MODULE_GLOBALS(test_hello_world) 
 */  

#ifdef ZTS  
#define TEST_HELLO_WORLD_G(v) TSRMG(test_hello_world_globals_id, zend_test_hello_world_globals *, v)  
#else  
#define TEST_HELLO_WORLD_G(v) (test_hello_world_globals.v)  
#endif  

#endif  /* PHP_TEST_HELLO_WORLD_H */  

test_hello_world.cc
#ifdef HAVE_CONFIG_H  
#include "config.h"  
#endif  

#include "php.h"  
#include "php_ini.h"  
#include "ext/standard/info.h"  
#include "test_hello_world.h"  
#include "string"  

using namespace std;  

/* If you declare any globals in php_test_hello_world.h uncomment this: 
   ZEND_DECLARE_MODULE_GLOBALS(test_hello_world) 
 */  

function_entry test_hello_world_functions[] = {  
    PHP_FE(hello_world, NULL)  
    {NULL, NULL, NULL}  
};  

zend_module_entry test_hello_world_module_entry = {  
#if ZEND_MODULE_API_NO >= 20010901  
    STANDARD_MODULE_HEADER,  
#endif  
    "test_hello_world",  
    test_hello_world_functions,  
    PHP_MINIT(test_hello_world),  
    PHP_MSHUTDOWN(test_hello_world),  
    NULL, //RINIT  
    NULL, //RSHUTDOWN  
    PHP_MINFO(test_hello_world),  
#if ZEND_MODULE_API_NO >= 20010901  
    "$Revision: 1.5 $",  
#endif  
    STANDARD_MODULE_PROPERTIES  
};  

extern "C" {  
#ifdef COMPILE_DL_TEST_HELLO_WORLD  
    ZEND_GET_MODULE(test_hello_world)  
#endif  
}  

PHP_MINIT_FUNCTION(test_hello_world)  
{  
    return SUCCESS;  
}     

PHP_MSHUTDOWN_FUNCTION(test_hello_world)  
{  
    return SUCCESS;  
}     

PHP_MINFO_FUNCTION(test_hello_world)  
{  
    php_info_print_table_start();  
    php_info_print_table_header(2, "test_hello_world support", "enabled");  
    php_info_print_table_end();  
}     

PHP_FUNCTION(hello_world)  
{  
    string ret("hello world");  
    RETURN_STRING(const_cast(ret.c_str()), 1);  
}  

config.m4
PHP_ARG_ENABLE(test_hello_world, whether to enable test_hello_world support,  
Make sure that the comment is aligned:  
[  --enable-test_hello_world           Enable test_hello_world support])  

if test "$PHP_TEST_HELLO_WORLD" != "no"; then  
    PHP_SUBST(TEST_HELLO_WORLD_LIBADD)  
    PHP_NEW_EXTENSION(test_hello_world, test_hello_world.cc, $ext_shared)  
    PHP_REQUIRE_CXX  

    PHP_ADD_INCLUDE(/usr/include)  
    PHP_ADD_LIBRARY_WITH_PATH(stdc++, /usr/lib, TEST_HELLO_WORLD_LIBADD)  
    OS=`uname`;  
    if test $OS = "FreeBSD"; then  
        CPPFLAGS="$CPPFLAGS -Wno-error -Wall -g"
    else  
        CPPFLAGS="$CPPFLAGS -Wno-error -Wall -g -m32 -lstdc++"
    fi  
fi  

編譯
$ phpize

$ ./configure

$ make
如果編譯成功,可以看到如下畫面



將設定檔放入下列路徑/etc/php5/conf.d/test_hello_world.ini,php才知道需要載入此模組
extension = test_hello_world.so

將編譯完成的.so放入php的library中
/usr/lib/php5/20090626+lfs/test_hello_world.so



重起apache服務
$ service apache2 restart

重新測試test.php
<?php
echo hello_world();
?>

若需要清除編譯結果,指令如下
$ make clean
$ phpize --clean











 
疑難排解
如果遇到錯誤訊息undefined symbol: _ZNSs4_Rep20_S_empty_rep_storageE

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20090626+lfs/yahoo_hello_world.so' - /usr/lib/php5/20090626+lfs/yahoo_hello_world.so: undefined symbol: _ZNSs4_Rep20_S_empty_rep_storageE in Unknown on line 0

解決方法
加上-lstdc++在CPPFLAGS中

參考: http://stackoverflow.com/questions/11939934/c-apache-module-fails-on-znss4-rep20-s-empty-rep-storagee



2013年8月23日 星期五

Ubuntu 13.04安裝筆記

SSD硬碟開啟TRIM功能

確認SSD硬碟是否支援TRIM
$ sudo hdparm -I /dev/sda | grep "TRIM supported"


編輯/etc/fstab

需要加上TRIM的磁區,於errors前加入noatime,nodiratime,discard,
並將log相關的設定放入tmpfs減少SSD存取

將SSD trimming放入daily job
編輯/etc/cron.daily/trim,寫入如下設定








更改權限
$ sudo chmod +x /etc/cron.daily/trim

參考資料:
http://yblog.org/archive/index.php/11734
http://www.webupd8.org/2013/01/enable-trim-on-ssd-solid-state-drives.html

gcin

加入repository
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 835AB0E3




安裝
$ sudo apt-get update
$ sudo apt-get install gcin

到語言設定去設定輸入法,之後登出再登入

解決icon消失的問題,可啟動gcin-tools,進入"外觀設定"=>"面板狀態(tray)"=>"Unity indicator"叫出

參考資料:
http://hyperrate.com/thread.php?tid=28044


Gnome-do

安裝
$ sudo apt-get install gnome-do
手動啟動後,調整熱鍵跟開機自動啟動選項,登出再登入即可生效

Pidgin

安裝
$ sudo add-apt-repository ppa:pidgin-developers/ppa
$ sudo apt-get update
$ sudo apt-get install pidgin

支援右上角訊息
$ sudo apt-get install pidgin-libnotify

設定支援office communicator
需要使用SIPE
http://sipe.sourceforge.net/
$ sudo apt-get install libglib2.0-dev intltool build-essential libnss3-dev libxml2-dev libgtk2.0-dev libpurple-dev
$ tar -xzvf pidgin-sipe-1.6.2.tar.gz
$ cd pidgin-sipe-1.6.2
$ ./configure --prefix=/usr
$ make
$ sudo make install
重新啟動pidgin就會看到office communicator的選項
記得不需要特別設定server等等,只需要設定username跟login都用mail即可

Dropbox

安裝
$ sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 5044912E
新增 deb http://linux.dropbox.com/ubuntu/ raring main
$ sudo apt-get update
$ sudo apt-get install dropbox

Font
複製到ttf檔案到/usr/share/fonts/truetype/裏面 fc-cache -f -v

PCman
$ sudo apt-get install pcmanx-gtk2

Perforce
下載後,將bin內檔案放入/usr/bin,lib內p4v目錄放入/usr/lib/ 設定p4v.desktop放入/usr/share/applications/

[Desktop Entry]
Type=Application
Name=P4V
Comment=Perforce Visual Client
Icon=/usr/lib/p4v/P4VResources/icons/p4v_48_high.png
Exec=/usr/bin/p4v
Terminal=false
Categories=Development

VMWare

安裝
$ chmod 755 VMware-Player-5.0.2-1031769.x86_64.bundle
$ sudo ./VMware-Player-5.0.2-1031769.x86_64.bundle

kernel升級完掛點,直接重裝最快
$ sudo vmware-installer --uninstall-product vmware-player


移除惱人的menu bar
$ sudo apt-get autoremove appmenu-gtk appmenu-gtk3 appmenu-qt

關閉按到alt會跳出command的設定法
到keyboard的shortcut設定,將key to show the HUD設定為Disabled (使用backspace按鈕)

參考資料
http://askubuntu.com/questions/122209/how-do-i-modify-or-disable-the-huds-use-of-the-alt-key

Java
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo update-java-alternatives -s java-7-oracle

Chrome
$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - deb http://dl.google.com/linux/chrome/deb/ stable main
$ sudo apt-get update
$ sudo apt-get install google-chrome-stable

Gnome
$ sudo add-apt-repository ppa:webupd8team/gnome3
$ sudo apt-get update
$ sudo apt-get install gnome-shell-extensions-gpaste compiz
$ sudo apt-get install gnome-session-fallback