PHP编写扩展来调用动态链接库

PHP编写扩展来调用动态链接库

💡 原文中文,约2500字,阅读约需6分钟。
📝

内容提要

本文介绍在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()查看。

🏷️

标签

➡️

继续阅读