项目需求:
之前做项目遇到了一个需求: 需要对接c/c++封装的so库,需要用php调用so库里面的方法。
需求设想:
接触之初,脑海中脑补了下这个需求应该怎么整: 没搞过啊,是不是把这个so库文件当做类,然后引用这个类再执行类里的方法。(哈哈,很单纯无知的想法)
拿到so库后,查看了下,这封装过了的,咋引用~~。 查找一番后确定了大致的实施方法: 增加php底层扩展方法,在扩展中引入库进行编译,编译成功生成php的引用扩展库,即可直接调用扩展库方法。
实施测试阶段:
因为是引用c++的扩展库,库里引用和opencv的一些扩展库,里面需要很多配套的扩展,一个萝卜一个坑,慢慢得趟出了很多坑,也获得了很多萝卜。
萝卜1: 编译中报出各种错,不是缺少这个扩展,就是缺少那个扩展,就得针对于各种缺少的各种安装,此过程中了解了很多扩展库的作用。
萝卜2: 系统性得了解了巩固了linux的各种命令,重温了下C语言的语法与so库的封装。
实施阶段:
因为是需要用到php的源码增加扩展,先现在一份和当前php环境版本一致的源码。下载地址: http://php.net/downloads.php
将so库的存放路径写入配置中保存(各个配置的环境路径也许会有不同) 打开 cd /etc/ld.so.conf.d/ vim local.conf 将so库存放路径/usr/local/lib写入保存
解压源码包(路径没要求) 打开解压后的文件夹里的 ext文件夹,里面储存的是php自带的一些扩展目录,我们所要做的就是在里面再加一个我们需要的扩展。
开始创建一个模块test: 执行命令: sudo ./ext_skel --extname=test
执行完会生成一个test的模块文件夹,打开test cd test
需要修改一些文件 给需要修改的文件权限 sudo chmod 777 config.m4 php_test.h test.c
1> 先修改 php_test.h 在声明方法下 增加一个你自己定义的调取so库的方法 如增加 test_add 方法:
PHP_FUNCTION(confirm_suone_compiled); /* For testing, remove later. */
PHP_FUNCTION(test_add); //声明此函数 (后面test.c中将用到)
2> 修改config.m4:
PHP_ARG_WITH(test, for test support, //放开此两行的注释 __WITH 是引用的外部库文件又引用了其他链接库 如果是引用单一的一个so文件,即放开 __ENABLE那两行
[ --with-test Include test support])
在底部引入扩展目录及文件,例如需添加的so库名称为 gettime.so
PHP_ADD_LIBRARY_WITH_PATH(gettime,/usr/local/lib,TEST_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(opencv_core,/usr/local/lib, TEST_SHARED_LIBADD) //引入一个opencv的链接库为例 此库都放在 /usr/local/lib 文件夹下
PHP_SUBST(TEST_SHARED_LIBADD) //加入此句表示此库为共享库
PHP_NEW_EXTENSION(test, test.c, $ext_shared)
3> 修改 test.c文件 (主函数文件)
const zend_function_entry test_functions[] = {
PHP_FE(confirm_test_compiled, NULL) /* For testing, remove later. */
PHP_FE(test_add,NULL) //加入此方法
{NULL,NULL,NULL}
// PHP_FE_END /* Must be the last line in suone_functions[] */
};
在文件底部,写函数调用方法
PHP_FUNCTION(test_add){ //test_add 是上面申明的方法名
char *name=NULL; //定义类型
long len;
long uid;
If(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name,&len ,&uid) == FAILURE) {
return;
}
char *data = Gettime(name,uid); //直接请求外部库gettime.so的 Gettime函数,传递参数,获取值
RETURN_STRINGL(data,strlen(data)+1,1); //返回结果值
}
每个库的请求方法和参数结合不相同,具体根据外部库所需要的参数为准
4> 文件修改完毕,现在执行编译命令,生成php可直接执行的底层库
sudo phpize
sudo ./configure --with-php-config=/usr/bin/php-config --with-test
sudo make test (先执行test 如果此步骤返回success,即可正常执行下面的安装,如果报错,先处理至没错)
sudo make install (安装完之后会生成一个新的库test.so 文件,将此文件复制到php的扩展库目录中 /usr/local/lib)
将 test.so 写入到php.ini的配置中 Extension=test.so 如果在之前的配置中引入了整个库文件目录,就不需要单独引入此文件
重启php服务
测试结果
新建一个test.php 文件
<?php
print_r(test_add("so库测试",1)); //test_add为扩展主方法里所写入的方法名,即可链接调用gettime.so的库文件里的方法了
?>