Hello World: 第一个PHP扩展
目标
创建一个名为 hello 的 PHP 扩展,并实现里面唯一的函数 hello_world,作用是打印出 "Hello World" 字符串。
前提条件
一台已经安装了 C 编译器、PHP 运行环境的电脑,一个称手的文本编辑器。
重要提示:不要试图在 Windows 下写 PHP 扩展,Visual C、MinGW 的编译器都不好用,我曾经捣鼓了一个多星期也没能在 Windows 下编译成功过。所以至少要在一个 Unix 环境下进行。Mac 和各种 Linux 环境都可以。
下载 PHP 源代码
先用 php -v 确定系统上的 PHP 版本,再到 php.net 上下载相应的源代码包。解压到某个目录下,如 php5-5.3.5。源代码目录里,ext 目录下即是所有的 PHP 扩展所在的地方,其他的目录暂时不必考虑。
生成 PHP 扩展的框架代码
在 php5-5.3.5/ext 目录下,有一个名为 ext_skel 的文件,这是用来创建扩展的一个简便的工具。确保它有可执行权限(chmod u+x ext_skel),在终端下执行
./ext_skel --extname=hello
即会在 ext 目录下创建一个 hello 的目录,里面是初始的骨架代码。下一步的任务是创建 hello 扩展,并实现 hello_world 函数。
编辑 config.m4
用文本编辑器打开 ext/hello/config.m4,里面有大量的注释说明(以 dnl 开头的行),基本上已经把很多问题说明白了。这里要做的就是把
dnl PHP_ARG_ENABLE(hello, whether to enable hello support,dnl Make sure that the comment is aligned:dnl [ --enable-hello Enable hello support])
这三行取消注释。这样在接下来的编译时,可以用 ./configure --enable-hello 来编译我们刚刚写的扩展。
重新生成 configure
回到源代码根目录,运行 ./buildconf --force,会激活 configure --enable-hello 参数。如果你在运行 buildconf 时报下面的错误:
buildconf: Your version of autoconf likely contains buggy cache code. Running vcsclean for you. To avoid this, install autoconf-2.13.
请安装 autoconf-2.13(ubuntu 懒人的用法)
sudo apt-get install autoconf2.13
编译扩展
此时的 hello 扩展已经可以编译了,虽然还没有实现其中的 hello_world 函数。先编译一下,确保没有环境配置上的问题。
./configure --enable-hellomake
经过一段时间(其实是把整个 PHP 也编译出来了),用
./sapi/cli/php -f ext/hello/hello.php
检查一下扩展编译情况。不出意外的话,应该提示
Functions available in the test extension:confirm_hello_compiledCongratulations! You have successfully modified ext/hello/config.m4. Module hello is now compiled into PHP.
编写 hello_world 函数
声明函数:打开 ext/hello/php_hello.h,在
PHP_MINIT_FUNCTION(hello);PHP_MSHUTDOWN_FUNCTION(hello);PHP_RINIT_FUNCTION(hello);PHP_RSHUTDOWN_FUNCTION(hello);PHP_MINFO_FUNCTION(hello);
后面添加
PHP_FUNCTION(hello_world);
即在扩展的头文件中声明了 hello_world 的函数的原型。PHP_FUNCTION 是用来定义 PHP 函数的 C 语言宏。至于宏展开后的样子,几乎不用去想。只管用就可以了。
实现函数:打开 hello.c,在文件的末尾添加
PHP_FUNCTION(hello_world){ php_printf("Hello World");return;}
这里即是 hello_world 函数的实现。php_printf 的作用是向 SAPI 输出一段字符串,类似于 PHP 语言中的 echo。
接下来还需要将 hello_world 函数注册到 zend_module_entry,这样这个函数才能在 PHP 程序中变成“可见”的。找到
const zend_function_entry hello_functions[]={ PHP_FE(confirm_hello_compiled, NULL)/* For testing, remove later. */{NULL, NULL, NULL}/* Must be the last line in hello_functions[] */};
将其修改为:
const zend_function_entry hello_functions[]={ PHP_FE(confirm_hello_compiled, NULL)/* For testing, remove later. */ PHP_FE(hello_world, NULL){NULL, NULL, NULL}/* Must be the last line in hello_functions[] */};
此时整个的 hello 扩展的代码就编写完了。最后再来 make 一下。
测试
在终端下运行 sapi/cli/php -r 'hello_world();echo "/n";',如果看到输出“Hello World”,就成功了。
如何把扩展编译成 .so 文件
上面编译的结果是把 hello 扩展编译进了 PHP 核心中。如果想要编译成 .so 扩展,以便发布出去的话。需要使用
./configure --enable-hello=sharedmake
这样编译完成后,会在 modules 目录下生成 hello.so 文件。把它复制到你的 PHP 运行环境的 extension_dir 下就可以像其他扩展一样使用了。需要注意的是 PHP 版本。如果你是在 PHP 5.3.5 的源代码环境中编译的扩展,则生成的 .so 文件只能用在 PHP 5.3.5 的运行环境中。
最后提一下,如果对 PHP 扩展有兴趣,可以看看《Extending and Embedding PHP》这本书,作者还是个 MM。目前没有中文版,英文电子版的自己搜。
摘自 lostwolf blog
最近更新
随机推荐
- 我用电脑黑了全世界(亡命天涯,一百章
- 黑客泄露50多万台服务器、路由器和物
- PEAR Net_Ping 'ping()'函数任意变量
- Linux kernel do_brk()参数边界检查不
- 三星称将尽快发布补丁修复Exynos处理
- FireFox 3.0.2版 修复6个危急漏洞
- 黑客经济产业链成形 投票机成敛财工具
- 如果马云赢了,这个民族就输了
- 受1折汇启发?1折网5万元收购域名1zw
- 国内安全公司率先发布DirectShow漏洞
- Snapchat遭攻击:460万用户信息泄露
- 购票高峰日12306又崩溃:显示有票却无
- MS06-035:Server服务中漏洞可能允许远
- 360推出手机搜索引擎:雷电搜索
- Linux VServer Project ProcFS弱共享
- Mozilla火狐OS手机开售 开放应用支付
- TR Forum SQL注入及认证绕过漏洞
- 微软更新2个DirectX漏洞补丁 已提供补
- 互联网电视从新兴企业切入
- 携程隐私泄露门启示:酒店服务更易出