首页 > Php, Zend API, 每日一日 > 如何在PHP扩展中引用第三方的C++类库

如何在PHP扩展中引用第三方的C++类库

还是360指数项目,需要用到Query归一化,但是公司内只有c++版本的,数据分析的同事用的都是那个二进制可执行文件来处理,但是我们前端又不可能跑system()方法吧,太不安全了,所以要来了源代码,打算封装成一个php扩展。
下边就讲一下我的封装过程。

首先,要到了Query归一化的C++版本源代码。

query归一化

query归一化

引用第三方的类库有两种方法,一种是静态引用,一种是动态引用,推荐使用静态引用,因为静态引用的情况下,会把类库打包到php的扩展.SO文件中,这样我们不必担心依赖关系,带着类库到处跑了。

先用gcc产生.o文件,再用.o产生 最终的静态库 .a 文件

gcc -c -fpic queryword.cpp tradmap.cpp transcode.cpp  -I . -O2
ar -r libqueryword.a queryword.o tradmap.o transcode.o

上边图中有产生的.o 和 .a文件

如果要动态编译so的话,就是这个:

gcc -c -fpic -O3 queryword.cpp tradmap.cpp transcode.cpp -I .
gcc -shared queryword.o transcode.o tradmap.o -o libqueryword.so

好,现在有了libqueryword.a静态库,我们就可以开始做我们的扩展了。

先使用ext_skel工具生成我们框架的骨架.
./ext_skel –extname=queryword

把上边的静态库放到 ./lib 目录下。

然后修改config.m4文件。
去掉一些注释符 dnl, 再添加两行,最后config.m4里,有用的就是这几行。

PHP_ARG_ENABLE(queryword, whether to enable queryword support,
Make sure that the comment is aligned:
[  --enable-queryword           Enable queryword support])                 

if test "$PHP_QUERYWORD" != "no"; then
    PHP_ADD_INCLUDE(./lib)
    PHP_ADD_LIBRARY(stdc++, 1, QUERYWORD_SHARED_LIBADD)
    PHP_ADD_LIBRARY_WITH_PATH(queryword, ./lib, QUERYWORD_SHARED_LIBADD)
    PHP_REQUIRE_CXX()
    PHP_SUBST(QUERYWORD_SHARED_LIBADD)                                        

  PHP_NEW_EXTENSION(queryword, queryword.cpp, $ext_shared)
fi

其中:
PHP_REQUIRE_CXX()用于指定这个扩展用到了C++
PHP_ADD_LIBRARY(stdc++, 1, QUERYWORD_SHARED_LIBADD) 用于将标准C++库链接进入扩展
PHP_NEW_EXTENSION用于指定有哪些源文件应该被编译,文件和文件之间用空格隔开.ext_skel默认生成的模块框架是针对C的,我们要使用C++,那以上说明的两个宏就是必须的.另外还要把queryword.c改名成queryword.cpp,所以PHP_NEW_EXTENSION原本包括的queryword.c也要修改.

默认生成的queryword.c(现在改名为queryword.cpp)了,已经包含了一个测试性质的导出函数,通过那个例子就可以大概明白怎么添加自己的函数了. zend_function_entry是导出函数列表, zend_module_entry描述了模块的信息. 不过因为是C++了,还是有几点要修改的,否则跑不起来:
1.cpp中自带的include,需要用extern “C”修饰。
改后如下:

extern "C" {
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif                                      

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_queryword.h"
#include <string.h>
}                                           

#include "queryword.h"   /*这些是自己加的*/
#include "valvec.hpp"

2.ZEND_GET_MODULE也要用extern “C”修饰,这里注意的是,修饰 ZEND_GET_MODULE ,用的是宏。

 #ifdef COMPILE_DL_QUERYWORD
 BEGIN_EXTERN_C()
 ZEND_GET_MODULE(queryword)
 END_EXTERN_C()
 #endif

再说明下,用到的第三方类库的方法,需要声明,上边的extern “C”下边的两个文件,就是我声明的要调用第三方类库的方法的定义。
比如:
放在 include 目录下的 queryword.h 内容如下:

 int query_init();
 int query_process(char *buf, int len, char *res, int rlen);
 void query_destroy();

再然后就是编辑自己的代码了,声明一个方法,并在自己的方法里调用第三方的库方法。最后RETURN结果。

这里就不详细说了,,跟自己的模块用法有关。

写好了之后,就一切ok了。

 

剩下的就是 phpize, ./configure , make …等等了。

 

——append  @ 2014-09-04

后期的谈谈项目也封装了一个扩展,就在组内进行了一次分享,有个ppt,分享给大家。

https://fukun.org/dd_share/c-php-extension/ppt.html

  1. 还没有评论
评论提交中, 请稍候...

留言

可以使用的标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Trackbacks & Pingbacks ( 0 )
  1. 还没有 trackbacks