这两天需要编译一个PHP扩展来实现特定的功能,参考了网上N多文章,最后发现两件宝贝,其一是php_screw,另外一件是Cygwin。
首先编译php_screw,以便有个感性的印象,编译通过没问题,然后自己试图往里增加一些代码,磕磕碰碰地最后也编译成功了。可是放到Apache上试用时,却经常出现内存读写异常,修修改改了好久还没无法解决。
于是,想自己重头开始做,参考php_screw往里一点点添代码,看看能不能解决问题。
根据网上教程,在Cygwin里用命令:
php ext_skel_win32.php --extname=mytest
生成测试用程序框架,然后直接编译框架,一切都很顺利,再往里增加一个功能函数,放到Apache测试,也都正常,但到了往下面两个函数:
PHP_MINIT_FUNCTION(mytest)
和
PHP_MSHUTDOWN_FUNCTION(mytest)
的 return SUCCESS 前面增加
CG(extended_info) = 1;
,然后再编译,则出现了编译错误:
Deleting intermediate files and output files for project 'mytest - Win32 Debug_TS'. --------------------Configuration: mytest - Win32 Debug_TS-------------------- Compiling... mytest.c Linking... Creating library Debug_TS/php_mytest.lib and object Debug_TS/php_mytest.exp mytest.obj : error LNK2001: unresolved external symbol _compiler_globals_id ..\..\Debug_TS/php_mytest.dll : fatal error LNK1120: 1 unresolved externals Error executing link.exe. Creating browse info file... php_mytest.dll - 2 error(s), 0 warning(s)
网上搜索了好久,我试了都不行,所以怀疑是编译器配置的问题,于是打开php_screw和mytest两个工程,对编译参数一项项比对,最后发现:
自动生成的编译参数如下Project --> Setting --> C/C++ -->Preprocessor definitions::
ZEND_DEBUG=1,WIN32,NDEBUG,_WINDOWS,_MBCS,_USRDLL,MYTEST_EXPORTS, COMPILE_DL_MYTEST,ZTS=1,ZEND_WIN32,PHP_WIN32,HAVE_MYTEST=1,LIBZEND_EXPORTS
而php_screw的对应参数则如下:
ZEND_DEBUG=0,WIN32,NDEBUG,_WINDOWS,_MBCS,_USRDLL,SCREW_EXPORTS, COMPILE_DL_SCREW, ZTS=1,ZEND_WIN32,PHP_WIN32,HAVE_SCREW=1
,对比可以发现:
1、自动生成框架的 ZEND_DEBUG=1, 而php_screw的 ZEND_DEBUG=0;
2、自动生成框架的参数中多一个 LIBZEND_EXPORTS ;
我于是对这两个参数分别测试:
1、把 ZEND_DEBUG=1 改成 ZEND_DEBUG=0,再编译,报错如下:
Deleting intermediate files and output files for project 'mytest - Win32 Debug_TS'. --------------------Configuration: mytest - Win32 Debug_TS-------------------- Compiling... mytest.c Linking... Creating library Debug_TS/php_mytest.lib and object Debug_TS/php_mytest.exp mytest.obj : error LNK2001: unresolved external symbol _compiler_globals_id ..\..\Debug_TS/php_mytest.dll : fatal error LNK1120: 1 unresolved externals Error executing link.exe. Creating browse info file... php_mytest.dll - 2 error(s), 0 warning(s)
2、再把 LIBZEND_EXPORTS 去掉,再编译,错误消失:
Deleting intermediate files and output files for project 'mytest - Win32 Debug_TS'. --------------------Configuration: mytest - Win32 Debug_TS-------------------- Compiling... mytest.c Linking... Creating library Debug_TS/php_mytest.lib and object Debug_TS/php_mytest.exp Creating browse info file... php_mytest.dll - 0 error(s), 0 warning(s)
3、再把 ZEND_DEBUG=0 重新改成 ZEND_DEBUG=1,再编译,无错:
Deleting intermediate files and output files for project 'mytest - Win32 Debug_TS'. --------------------Configuration: mytest - Win32 Debug_TS-------------------- Compiling... mytest.c Linking... Creating library Debug_TS/php_mytest.lib and object Debug_TS/php_mytest.exp Creating browse info file... php_mytest.dll - 0 error(s), 0 warning(s)
所以,问题是由于 LIBZEND_EXPORTS 参数引起的,但由于对VC不熟且对Zend API更面生的缘故,只能是知其然而不可知其所以然也;