Developing custom PHP extensions PECL Tutorials 从源程序编译 DLL
想了很久怎么给这篇文章起标题,本文是针对入门型的,定位在 开发或者学习 PHP C/C++扩展的朋友的初级教程。有两个理由需要自己编写PHP扩展。第一个理由是:PHP需要支持一项她还未支持的技术。这通常包括包裹一些现成的C函数库,以便提供PHP接口。例如,如果一个叫FooBase的数据库已推出市场,你需要建立一个PHP扩展帮助你从PHP里调用FooBase的C函数库。这个工作可能仅由一个人完成,然后被整个PHP社区共享(如果你愿意的话)。第二个不是很普遍的理由是:你需要从性能或功能的原因考虑来编写一些商业逻辑。
本门技术我大概花了七个小时来整理技术,并发布这边博文,暂时的功能是在windows平台上生成DLL文件。
技术关键字:windowsMicrosoft Visual C++ 6.0源程序编译PHPExtensionDLL
What is PECL?
PECL (PHP Extension Community Library),PHP的扩展库,它提供了一系列已知的扩展库,由C++等其他语言编写而成,多数以Dll(动态链接库)的形式体现,为比PEAR更快,但是与PEAR
不同的是,PECL需要在服务器上配置并被注册到主机中。
PECLis a repository for PHP Extensions, providing a directory of all known extensions and hosting facilities for downloading and development of PHPextensions.
官方:http://pecl.php.net/
开发环境的搭建
PHP 的源码包,这个可以到 http://www.php.net/downloads.php去下载,记得我们是要源码包(Complete Source Code)而不是PHP 的二进制代码包(Windows Binaries)。本文所采用是 PHP 5.2.12 的源码包。
随便贴出下载地址:http://cn.php.net/distributions/php-5.2.12.tar.gz
注:千万别覆盖当前windows下的php,因为你下载的是linux上运行的源码程序,我们用的只是他需要编译的头文件,例如php.h。
解压开php-5.2.12.tar.gz
除此之外我们还需要一个 php5ts.lib (若用 PHP 4 的源码包则需要的是 php4ts.lib)的文件。这在PHP 二进制代码包的 dev 目录(php4ts.lib 则是直接放在二进制代码包的根目录)下可以找到。
该源码包解压到某个目录,我们可以看到main、Zend、win32、TSRM、regex、ext 等目录。
现在记住重要的地方:拷贝main、Zend、win32、TSRM、regex、ext\standard到windows php 安装目录中。暂时先不解释为什么。因为后面我们出现编译错误时会提醒你的,这些都是项目中必须要用到的。
http://blog.lixiphp.com/wp-content/uploads/2009/12/php-directory.jpg这就是目前windows下PHP目录中的文件夹。
我们在这里使用的 IDE 是 VC++ 6.0 简体中文版本 。需要次软件的在下面评论中留下你的Email和QQ号或者在联系页面查看我的联系方式,我直接传文件给你。
项目开始
在菜单中选择 【文件】 -> 【新建】 -> 【工程】 来创建这个扩展的项目文件。
工程类型为“Win32 Dynamic-Link Library”。工程名称为:lixiphp,在本例中我们的扩展名字为 lixiphp,位于 PHP\ext目录下。
在抚琴居 《扩展 PHP》一文中使用的类型是 Win32 Project ,我第一次做的时候选择 Win32 Console Application,结果Link 时会出现了错误。
在 “您希望创建什么类型的DLL?”中,选择 “一个空的 DLL 工程”。
Onthe next menu choose “An empty DLL project” and click the finish button. A new window should open up and show you all the information relating to the project; click the OK button again。
现在我们将扩展的源代码文件lixiphp.c 新建/添加到 lixiphp扩展的项目文件当中。
注意:此处新建文件为lixiphp.c不是lixiphp.cpp。
配置项目属性
1、删除 Win32 Debug,添加个性Release。
① 组件 -> 配置 -> 选中Win32 Debug -> 删除
此时就剩下 Win32 Release。 因为生成DLL 不需要Debug,所以删除掉。
http://blog.lixiphp.com/wp-content/uploads/2009/12/remove-debug.jpg删除 Win32 Debug
② 组件 -> 配置 -> 添加配置 Release_lixiphp, 配置拷贝从Win32 Release。平台任然为Win32。
最后效果为下图:
http://blog.lixiphp.com/wp-content/uploads/2009/12/win32-Release_lixiphp.jpg
2、设置工程属性
http://blog.lixiphp.com/wp-content/uploads/2009/12/project-setting-640x422.jpg
① C/C++ tab 设置
On the C/C++ tab,General Category, add the following preprocessor definitions:
A 选择分类:预处理器
讲预处理器定义设置为:
ZEND_DEBUG=0,COMPILE_DL_LIXIPHP_MOD,ZTS=1,ZEND_WIN32,PHP_WIN32,WIN32,_DEBUG,_CONSOLE,_MBCS
附加包含路径设置为:
../..,../../main,../../Zend,../../TSRM
自己根据相对路径算一算对不对,如果你按照我上面的做的话,是不会出问题的。 ../的意思上级目录。
效果如下图:
http://blog.lixiphp.com/wp-content/uploads/2009/12/preprocessor-definition.jpg
B 选择分类:Code Generation
In the Code Generation Category, change Use run-time Library to “Multithreaded DLL”.
效果如下图:
http://blog.lixiphp.com/wp-content/uploads/2009/12/Code-Generation.jpg
② 连接设置
分类:常规
输出文件名为:Release_lixiphp/php_lixiphp.dll
对象/库对象最末尾添加 php5ts.lib, 如果你是PHP4 就添加 php4ts.lib,最后为:
kernel32.libuser32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.libole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib
Onthe Link tab in the General Category, change the Output file name to Release_lixiphp/php_lixiphp.dll . In future projects you will be able tochange the name to anything (*.dll). However, most PHP extensions come with the prefix php_ to indicate they are in-fact PHP extensions. (php_*.dll)
On the same tab (Link), same category (General), add php4ts.lib to Object/library modules.
这样,整个扩展项目文件的Release 版本就配置好了。
现在万事俱备,只欠编码了,让我们这就开始吧!
Copy PHP\dev\php5ts.lib 到你刚才建立的项目中,PHP4同理。
编写lixiphp.c代码
帮助
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* include standard header */
/* you will need to include this in all of your php extension projects*/
#include "php.h"
#include "ext/standard/info.h" /* for phpinfo() functions */
/* All the functions that will be exported (available) must be declared */
ZEND_FUNCTION(hello_lixi);
PHP_MINFO_FUNCTION(lixiphpmod);
/* Just a basic int to be used as a counter*/
inti;
/* function list so that the Zend engine will know what’s here */
zend_function_entry lixiphpmod_functions[] =
{
ZEND_FE(hello_lixi, NULL) {NULL, NULL, NULL}
};
/* module information */
zend_module_entry lixiphpmod_module_entry =
{
STANDARD_MODULE_HEADER, "LixiPHP", lixiphpmod_functions, NULL, NULL, NULL, NULL, PHP_MINFO(lixiphpmod), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};
#if COMPILE_DL_LIXIPHP_MOD
ZEND_GET_MODULE(lixiphpmod)
#endif
PHP_MINFO_FUNCTION(lixiphpmod)
{
php_info_print_table_start();
php_info_print_table_row(2, "LixiPHP Extension", "All Systems Go");
php_info_print_table_end();
}
ZEND_FUNCTION(hello_lixi)
{
zend_printf("Hello lixi, this is from http://blog.lixiphp.com!");
}
最后在compile 、build , Release_lixiphp目录中就会生成 php_lixiphp.dll。
至此整个编译过程结束。
使用extension dll
① 拷贝php_lixiphp.dll到 php/ext 目录中。
② 配置php.ini文件,添加extension=php_lixiphp.dll
③ 重启服务器
测试安装是否成功
http://blog.lixiphp.com/wp-content/uploads/2009/12/php_lixiphp-dll.jpg
调试代码如下:
帮助
1
2
3
4
<?php
hello_lixi();
phpinfo();
?>
或者使用 命令测试,命令如下:
php -r hello_lixi();
注意:php.exe的目录必须加入环境变量path中,不好请在评论中提问。
效果图如下:
http://blog.lixiphp.com/wp-content/uploads/2009/12/php-r-hello-lixi-640x178.jpg
最后慢慢享受一下自己成果吧!
本文功能简单,只为那些想学习extension dll 的phper们提供点基础知识。
错误解决
现在详解的错误方法是我在学习研究过程中遇到的。如果你严格按照上面的步骤,这一栏信息你完全可以飘过。只是针对那些从半路杀出来的,你可能在看其他文章和技术文档时出现错误,通过搜索引擎来到这儿的。不过我们同样欢迎你!
① php.h 文件不在配置环境中
ERROR:
fatal error C1083: Cannot open include file: ‘php.h’: No such file or directory
解决方法:
请查看本文的 “开发环境的搭建” 一栏,你肯定是没有安装 tar.gz源码,在Windows Binaries 二进制代码包中是无法编译的。
② phpinfo() functions 错误
ERROR:
fatal error C1083: Cannot open include file: ‘php.h’: No such file or directory
lixiphp.c(31) : warning C4013: ‘php_info_print_table_start’ undefined; assuming extern returning int
lixiphp.c(32) : warning C4013: ‘php_info_print_table_row’ undefined; assuming extern returning int
lixiphp.c(33) : warning C4013: ‘php_info_print_table_end’ undefined; assuming extern returning int
解决方法:#include “ext/standard/info.h” /* for phpinfo() functions */
关于standard的安装方法请查看本文的 “开发环境的搭建” 一栏,你没有拷贝源码包中的ext\standard
③ 编译通过,但是连接出错
ERROR:
——————–Configuration: helloworld – Win32 Release_TS——————–
Linking…
Creating library Release_TS/php_lixiphp.lib and object Release_TS/php_lixiphp.exp
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Release_TS/php_lixiphp.dll : fatal error LNK1120: 1 unresolved externals
执行 link.exe 时出错.
解决方法:
你的工程建立错误,请建立:Win32 Dynamic-Link Library 工程,我们做的DLL项目。
④ 无法连接php 内部函数,没有添加php5ts.lib
ERROR:
Linking…
Creating library Release_TS/lixiphp.lib and object Release_TS/lixiphp.exp
lixiphp.obj : error LNK2001: unresolved external symbol __imp__php_info_print_table_end
lixiphp.obj : error LNK2001: unresolved external symbol __imp__php_info_print_table_row
lixiphp.obj : error LNK2001: unresolved external symbol __imp__php_info_print_table_start
lixiphp.obj : error LNK2001: unresolved external symbol __imp__zend_printf
Release_TS/php_lixiphp.dll : fatal error LNK1120: 4 unresolved externals
解决方法:
工程 -> 设置 -> 链接 -> 常规 -> 添加php5ts.lib, 请查看本文 连接设置。
注:我遇到的错误就这样了,你有什么错误,请在评论中提交。
页:
[1]