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程序中的常见漏洞进行攻击
Oct 09 PHP
在smarty模板中使用PHP函数的方法
Apr 23 PHP
php用户注册页面利用js进行表单验证具体实例
Oct 17 PHP
php中url函数介绍及使用示例
Feb 13 PHP
php json_encode()函数返回json数据实例代码
Oct 10 PHP
php中$_GET与$_POST过滤sql注入的方法
Nov 03 PHP
php实现数组中索引关联数据转换成json对象的方法
Jul 08 PHP
php给图片加文字水印
Jul 31 PHP
php数据访问之查询关键字
May 09 PHP
PHP实现的简单排列组合算法应用示例
Jun 20 PHP
php生成毫秒时间戳的实例讲解
Sep 22 PHP
php curl发送请求实例方法
Aug 01 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执行速率优化技巧小结
2008/03/15 PHP
PHP mb_convert_encoding文字编码的转换函数介绍
2011/11/10 PHP
PHP中使用mktime获取时间戳的一个黑色幽默分析
2012/05/31 PHP
laravel 错误处理,接口错误返回json代码
2019/10/25 PHP
Prototype最新版(1.5 rc2)使用指南(1)
2007/01/10 Javascript
JavaScript 调试器简介
2009/02/21 Javascript
for 循环性能比较 提高for循环的效率
2009/03/19 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
2013/10/15 Javascript
js动态改变select选择变更option的index值示例
2014/07/10 Javascript
Jquery轮播效果实现过程解析
2016/03/30 Javascript
Cookies 和 Session的详解及区别
2017/04/21 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
了解重排与重绘
2019/05/29 Javascript
Vue开发中遇到的跨域问题及解决方法
2020/02/11 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
原生JS运动实现轮播图
2021/01/02 Javascript
[54:45]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 Optic vs OG
2018/04/02 DOTA
python对字典进行排序实例
2014/09/25 Python
Python利用multiprocessing实现最简单的分布式作业调度系统实例
2017/11/14 Python
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
pandas 小数位数 精度的处理方法
2018/06/09 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
Python 给屏幕打印信息加上颜色的实现方法
2019/04/24 Python
Python求均值,方差,标准差的实例
2019/06/29 Python
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
美国宠物护理专家:Revival Animal Health
2020/01/05 全球购物
Abbott Lyon官网:女士手表、珠宝及配件
2020/12/26 全球购物
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
高中运动会入场词
2014/02/14 职场文书
爱国演讲稿500字
2014/05/04 职场文书
党的群众路线教育实践活动通讯稿
2014/09/10 职场文书
党员查摆四风问题思想汇报
2014/10/25 职场文书
刑事上诉状(无罪)
2015/05/23 职场文书
入门学习Go的基本语法
2021/07/07 Golang
MySQL 数据库范式化设计理论
2022/04/22 MySQL