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












