内容提要
本文介绍在Linux下用PHP扩展调用动态链接库的方法:编写C加法函数并编译为libadd.so,配置库搜索路径;用PHP源码的ext_skel生成扩展框架,在cadd.c中声明并实现add函数调用该库,经phpize、configure、make编译安装;最后在php.ini添加extension=cadd.so,分别验证命令行与网页调用。
延伸解读
动态库路径配置是运行成败的关键
文章特别强调,将 libadd.so 放入搜索路径后必须执行 sudo ldconfig 更新缓存。否则编译阶段可能不报错,但运行时因找不到库而失败。这提醒读者:动态库的“编译通过”与“运行可用”是两回事,路径缓存未刷新是常见坑点,部署新库后应主动验证。
扩展命名刻意区分库名与扩展名
作者将动态库命名为 add,而 PHP 扩展命名为 cadd,并在文中说明这是为了避免看代码时混淆。这种命名策略值得借鉴:当本地库函数与 PHP 扩展函数同名时,代码中 add(a, b) 既可能指库函数也可能指扩展函数,区分命名能降低维护时的理解成本。
CLI 与 FPM 需分别配置并重启
文章显示,命令行与网页端使用不同的 php.ini 路径,需各自添加 extension=cadd.so。网页端修改后还必须重启 php-fpm 服务才能生效。这说明扩展加载是进程级行为,读者在验证时应分别检查 CLI 和 FPM 的已加载扩展列表,避免只改一处导致一端可用另一端失败。
参数类型必须匹配 Zend 解析规则
示例中 PHP_FUNCTION(add) 使用 long int 接收参数,并通过 zend_parse_parameters 的 "ll" 格式解析,注释强调“必须用 long int”。这提示读者:PHP 扩展与 C 库之间的类型映射不是自动的,参数声明与解析格式不一致可能导致传值错误,编写扩展时应严格对照 Zend 引擎的类型约定。
Q&A
如何在Linux下用PHP扩展调用自己写的动态链接库?
主要步骤:1. 编写C函数并编译为动态库(如libadd.so),配置库搜索路径;2. 用PHP源码的ext_skel生成扩展框架;3. 在扩展中声明并实现PHP函数,调用动态库函数;4. 用phpize、configure、make编译安装;5. 在php.ini中添加extension=cadd.so;6. 验证命令行和网页调用。
如何让Linux系统找到自己编译的动态链接库?
在/etc/ld.so.conf.d目录下新建一个.conf文件,将库所在路径写入(一行一个),然后执行sudo /sbin/ldconfig更新缓存。不执行ldconfig的话,编译时没问题但运行时会出错。
用ext_skel生成PHP扩展框架后需要修改哪些文件?
需要修改两个文件:1. 在php_cadd.h中#endif前加入PHP_FUNCTION(add);声明函数;2. 在cadd.c的cadd_functions数组中添加PHP_FE(add, NULL),并实现PHP_FUNCTION(add)函数体,调用动态库的add函数。
PHP扩展中如何调用动态库函数并返回结果?
在PHP_FUNCTION(add)中,用zend_parse_parameters解析参数(类型用"ll"表示两个long),然后直接调用动态库的add(a, b),最后用RETURN_LONG(result)返回结果。注意变量必须用long int类型。
编译PHP扩展时如何指定链接动态库?
执行make时加上LDFLAGS=-ladd,表示链接时需要add库。然后sudo make install部署,扩展会自动复制到PHP扩展目录(如/usr/lib/php/20170718/)。
PHP命令行和网页端如何分别启用新扩展?
命令行:修改cli的php.ini(如/etc/php/7.2/cli/php.ini),添加extension=cadd.so,用php -m确认。网页端:修改fpm的php.ini(如/etc/php/7.2/fpm/php.ini),添加同样内容,并重启php-fpm服务,通过phpinfo()查看。