Developing custom PHP extensions PECL Tutorials 从源程序编译 DLL

想了很久怎么给这篇文章起标题,本文是针对入门型的,定位在 开发或者学习 PHP C/C++扩展的朋友的初级教程。

有两个理由需 要自己编写PHP扩展。第一个理由是:PHP需要支持一项她还未支持的技术。这通常包括包裹一些现成的C函数库,以便提供PHP接口。例如,如果一个叫 FooBase的数据库已推出市场,你需要建立一个PHP扩展帮助你从PHP里调用FooBase的C函数库。这个工作可能仅由一个人完成,然后被整个 PHP社区共享(如果你愿意的话)。第二个不是很普遍的理由是:你需要从性能或功能的原因考虑来编写一些商业逻辑。

本门技术我大概花了 个小时来整理技术,并发布这边博文,暂时的功能是在windows平台上生成DLL文件。

技术关键字:windows Microsoft Visual C++ 6.0 源程序编译 PHP Extension DLL

What is PECL?

PECL (PHP Extension Community Library),PHP的扩展库,它提供了一系列已知的扩展库,由C++等其他语言编写而成,多数以Dll(动态链接库)的形式体现,为比PEAR更快,但是与PEAR

不同的是,PECL需要在服务器上配置并被注册到主机中。

PECL is a repository for PHP Extensions, providing a directory of all known extensions and hosting facilities for downloading and development of PHP extensions.

官方: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 安装目录中。暂时先不解释为什么。因为后面我们出现编译错误时会提醒你的,这些都是项目中必须要用到的。

 

这就是目前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 工程”。

On the 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,所以删除掉。

删除 Win32 Debug

② 组件 -> 配置 -> 添加配置 Release_lixiphp, 配置拷贝从Win32 Release。平台任然为Win32。

最后效果为下图:

2、设置工程属性

① 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

自己根据相对路径算一算对不对,如果你按照我上面的做的话,是不会出问题的。 ../的意思上级目录。

效果如下图:

B 选择分类:Code Generation
In the Code Generation Category, change Use run-time Library to “Multithreaded DLL”.

效果如下图:

② 连接设置
分类:常规
输出文件名为:Release_lixiphp/php_lixiphp.dll
对象/库对象最末尾添加 php5ts.lib, 如果你是PHP4 就添加 php4ts.lib,最后为:

kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib

On the Link tab in the General Category, change the Output file name to Release_lixiphp/php_lixiphp.dll . In future projects you will be able to change 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*/
int i;
 
/* 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
③ 重启服务器

测试安装是否成功

调试代码如下:

1
2
3
4
<?php
hello_lixi();
phpinfo();
?>

或者使用 命令测试,命令如下:

php -r hello_lixi();

注意: php.exe的目录必须加入环境变量path中,不好请在评论中提问。

效果图如下:

最后慢慢享受一下自己成果吧!
本文功能简单,只为那些想学习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, 请查看本文 连接设置。

注: 我遇到的错误就这样了,你有什么错误,请在评论中提交。

你可能感兴趣的:(C++,PHP,ext,C#,Zend)