準備環境
$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
$ 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