PHP中调用C/C++制作的动态链接库的教程


Posted in PHP onMarch 10, 2016

一般而言,php速度已经比较快,但是,对于一些较高级开发者而言,如果想要追求更快的速度,那毫无疑问可以通过自己写c代码,并编译为动态链接库(常为.so文件),然后php通过创建一个新的扩展(extension),并在扩展里调用该.so文件,同时对外暴露出php函数接口。
在实际使用中,只要调用该函数接口,即可使用底层更快速的c函数服务。

一、动态链接库(shared)

动态链接库的文件名后缀通常是 ".so"。在Windows系统中,其文件名后缀是".dll"。

程序如果是和动态连接库进行链接(link),程序运行时需要能够找到相应的动态链接库文件。

使用动态链接库存编译的程序在运行时要求用户的机器上必需也安装了相应的动态链接库文件,这些库文件需要放置在特定的目录,以让程序能够加载这些库。

虽然这似乎没有使用静态链接库的程序使用方便,但却减少了程序的大小。对于那些会被很多程序使用到的库,使用动态链接的好处就更加明显了。

动态链接库的制作:

gcc -shared -fPIC -o libmylib.so mylib.c  ; # 编译成为shared library

选项-fPIC在AMD64上是必须的,其它平台是则不是必要选项。

包含静态链接库到动态链接库中

编译动态链接库时,如果需要链接静态库,并把链接库的内容包含到要编译的动态库中,可以使用选项-Wl,--whole-archive。

例如:

gcc -shared -o libmylib.so -Wl,--whole-archive libmylib.a \
  -Wl,--no-whole-archive libother.a

上面的-Wl表示传递给linker(链接器)。

二、调用动态C/C++链接库
下面,本文的开发环境背景是CentOS release 6.5 。为了能够调用c库,我们的php 5.6.9,apache 2.4均是下载源码并编译的,不可直接通过yum安装!请注意。至于php和apache的源码编译本文不提,只要注意在configure打开合适开关即可。

具体步骤如下:
将共享库.so添加入系统配置中(假设共享库名为 'libhello.so')

cp libhello.so /usr/local/lib
 echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
 /sbin/ldconfig

在php/ext目录下创建扩展头文件,取名为myfunctions.def
在该文件里填写c函数声明即可。每个函数一行。

string hello(int a)
 int hello_add(int a, int b)

使用ext_skel搭建扩展骨架

./ext_skel --extname=myfunctions --proto=myfunctions.def

打开config.m4 中的enable开关

PHP_ARG_ENABLE(myfunctions, whether to enable myfunctions support, 
 [ --enable-myfunctions        Include myfunctions support])

上面把扩展骨架建立好了,下面重新配置php (下面是我个人配置文件,读者需要结合自己情况修改)

./buildconf --force  //生成新配置脚本
 './configure' '--prefix=/usr/local/php' '--with-libdir=lib64' '--enable-fpm' '--with-fpm-user=php-fpm' '--with-fpm-group=www--enable-mysqlnd' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-pdo-mysql=mysqlnd' '--enable-opcache' '--enable-pcntl' '--enable-mbstring' '--enable-soap' '--enable-zip' '--enable-calendar' '--enable-bcmath' '--enable-exif' '--enable-ftp' '--enable-intl' '--with-openssl' '--with-zlib' '--with-curl' '--with-gd' '--with-zlib-dir=/usr/lib' '--with-png-dir=/usr/lib' '--with-jpeg-dir=/usr/lib' '--with-gettext' '--with-mhash' '--with-ldap' '--disable-fileinfo' '--with-config-file-path=/usr/local/php/etc' '--with-apxs2=/usr/local/httpd/bin/apxs' '--enable-myfunctions' // 配置

 记住!一定在末尾加上 —enable-myfunctions 。这样子才会被编译进php中。
当扩展编译进去了之后,就可以开始修改扩展里的myfunctions.c文件,在里面可以添加php->c的转接函数,在转接函数里可以调用.so内的函数。
比如要添加一个hello_add的php函数,里面可以调用c函数add(int a, int b)
a. 添加函数声明

PHP_FE(hello_add, NULL)

b. 添加php函数

PHP_FUNCTION(hello_add){ ... }

注意,在该函数里,如果调用了.so文件里的接口函数,那么待会在make的时候,要指定所使用的.so共享库,该共享库必须完成第1步中添加到系统配置的操作。
如果调用了.so文件,那么要在php/Makefile中添加

Extra_LDFLAG = -lhello //对应前面的libhello.so
Extra_libs = -lhello
(make clean)

每次修改完上面的c文件,都要重新make

make
make install

重启apache服务器

httpd -k restart

在phpinfo里可以看到新扩展,可以直接在php调用新扩展内的函数。

PHP 相关文章推荐
php设置编码格式的方法
Mar 05 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
Aug 07 PHP
php实现查看邮件是否已被阅读的方法
Dec 03 PHP
PHP上传图片进行等比缩放可增加水印功能
Jan 13 PHP
PHP中大于2038年时间戳的问题处理方案
Mar 03 PHP
php根据一个给定范围和步进生成数组的方法
Jun 19 PHP
php实现购物车功能(上)
Jul 23 PHP
Joomla实现组件中弹出一个模式(modal)窗口的方法
May 04 PHP
php mysql procedure实现获取多个结果集的方法【基于thinkPHP】
Nov 09 PHP
php如何修改SESSION的生存存储时间的实例代码
Jul 05 PHP
PHP ADODB生成HTML表格函数rs2html功能【附错误处理函数用法】
May 29 PHP
TP5框架实现签到功能的方法分析
Apr 05 PHP
php实现无限级分类查询(递归、非递归)
Mar 10 #PHP
Zend Framework教程之Application和Bootstrap用法详解
Mar 10 #PHP
Zend Framework教程之配置文件application.ini解析
Mar 10 #PHP
PHP浮点数的一个常见问题
Mar 10 #PHP
简单谈谈php浮点数精确运算
Mar 10 #PHP
PHP实现仿百度文库,豆丁在线文档效果(word,excel,ppt转flash)
Mar 10 #PHP
Zend Framework教程之Loader以及PluginLoader用法详解
Mar 09 #PHP
You might like
使用php验证复选框有效性的示例
2013/11/13 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
ThinkPHP3.2.2实现持久登录(记住我)功能的方法
2016/05/16 PHP
总结PHP内存释放以及垃圾回收
2018/03/29 PHP
PHP使用PhpSpreadsheet操作Excel实例详解
2020/03/26 PHP
图片自动缩小的js代码,用以防止图片撑破页面
2007/03/12 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
javascript字符串拼接的效率问题
2010/12/25 Javascript
ExtJS4利根据登录后不同的角色分配不同的树形菜单
2014/05/02 Javascript
JavaScript中this详解
2015/09/01 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
Bootstrap中的Panel和Table全面解析
2016/06/13 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
2016/08/19 Javascript
js提示框替代系统alert,自动关闭alert对话框的实现方法
2016/11/07 Javascript
javascript学习之json入门
2016/12/22 Javascript
JavaScript时间戳与时间日期间相互转换
2017/12/11 Javascript
JS浮点数运算结果不精确的Bug解决
2019/08/01 Javascript
js实现无缝轮播图效果
2020/03/09 Javascript
原生JS实现多条件筛选
2020/08/19 Javascript
vue将data恢复到初始状态 && 重新渲染组件实例
2020/09/04 Javascript
python实现从一组颜色中找出与给定颜色最接近颜色的方法
2015/03/19 Python
Ubuntu16.04/树莓派Python3+opencv配置教程(分享)
2018/04/02 Python
详解python使用pip安装第三方库(工具包)速度慢、超时、失败的解决方案
2018/12/02 Python
Python求一批字符串的最长公共前缀算法示例
2019/03/02 Python
django celery redis使用具体实践
2019/04/08 Python
python多线程扫描端口(线程池)
2019/09/04 Python
Python编程快速上手——Excel到CSV的转换程序案例分析
2020/02/28 Python
python实现KNN近邻算法
2020/12/30 Python
基于HTML5 Canvas的3D动态Chart图表的示例
2017/11/02 HTML / CSS
Speedo速比涛中国官方网站:全球领先泳装运动品牌
2018/04/24 全球购物
Farah官方网站:男士服装及配件
2019/11/01 全球购物
台湾全方位线上课程与职能学习平台:TibaMe
2019/12/04 全球购物
师德师风学习材料
2014/12/19 职场文书
公司开除员工通知
2015/04/22 职场文书
公司员工宿舍管理制度
2015/08/07 职场文书
win10识别不了U盘怎么办 win10系统读取U盘失败的解决办法
2022/08/05 数码科技