设为首页 收藏本站
查看: 1048|回复: 0

[经验分享] PHP扩展调用C++静态库

[复制链接]

尚未签到

发表于 2017-12-29 19:01:30 | 显示全部楼层 |阅读模式
概述
  php通过扩展方式,调用c++源码,这样做的理由有很多,当你搜到这篇文章时,相信你已经有自己的考虑了。
  写这篇博客的理由有二:


  • 整理下php扩展调用c++代码的过程。嗯,对,网上有很多类似的文章,不过对于php扩展c++的方式,很多文章在关键的地方并没有说明,或者说,大部分都是扩展调用c代码的。
  • 已经两年有余没写博客了,在这2017刚开始的时候,开个博客,开始新的旅程,也是不错的,哈哈。

大概目录


  • c++编译静态库
  • php 扩展编辑
  • 结语
  注:下面步骤的操作环境——系统macOS10.12.2,PHP版本 5.6.29.

c++编译静态库
  头文件:hello.h
  

#include<string>  
std::
string hello_joint(std::string a, std::string b);  

  实现头文件定义的函数:hello.cpp
  

#include "hello.h"  
std::
string hello_joint(std::string a, std::string b)  
{
  
std::
string str = a+b;  

return str;  
}   
  

  生成hello.o文件
  

g++ -c hello.cpp  

  生成静态库libhello.a文件
  

ar -r libhello.a hello.o  

  写个简单的test.cpp测试下:
  

1 #include<iostream>  
2 #include "hello.h"
  
3 int main()
  
4 {
  
5     std::string a = std::string("Hello ");
  
6     std::string b = std::string("World!");
  
7     std::cout<<hello_joint(a, b)<<std::endl;
  
8     return 0;
  
9 }
  

  编译
  

g++ test.cpp libhello.a   

  运行
  

./a.out   

  终端输出
  

Hello World!  

  这样,你的c++静态库制作完成。

php 扩展编辑
  如果要编辑php扩展,需要下载php源码,这里下载的是php-5.6.16。写文章的时候,才发现php源码版本和系统的php版本不一致。因为是先下载的php源码,然后通过brew install php56,不过,影响不大,不用纠结。
  运行如下命令,产生扩展文件夹january
  

./ext_skel --extname=january   

  命名为january,主要是不想跟c++源码hello产生任何关系,以免后面混淆,当然,也是因为想不出其他比较好的名字。

首先编辑config.m4,需要改的地方大概归结为三处:
  1、找到如下三行,并把前面的注释dnl去掉。
  

PHP_ARG_ENABLE(january, whether to enable january support,  Make sure that the comment
is aligned:
[

--enable-january           Enable january support])  

  2、找到如下的代码,并在它的下面加上相应代码,以支持c++调用。
  

if test "$PHP_JANUARY" != "no"; then  
dnl Write more examples of tests here...
  

  要加上的相应代码,注意其中的参数名。
  

if test "$PHP_JANUARY" != "no"; then  
dnl Write more examples of tests here...
  

  

  
PHP_ADD_INCLUDE(.
/include)  
PHP_ADD_LIBRARY(stdc
++, 1, JANUARY_SHARED_LIBADD)  
PHP_ADD_LIBRARY_WITH_PATH(hello, .
/lib, JANUARY_SHARED_LIBADD)  
PHP_REQUIRE_CXX()
  
PHP_SUBST(JANUARY_SHARED_LIBADD)
  

  3、同时,在该函数的最后一行,把january.c改为january.cpp
  

PHP_NEW_EXTENSION(january, january.cpp, $ext_shared)  




january.cpp需要做的工作比较多:
  1、重命名:把january.c改为为january.cpp;
  2、在两处地方加上EXTERN "C"标识,这点不要忘了:
  第一处加extern "C"{},并在下面加上需要的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_january.h"
  
}
  

  
#include<string>
  
#include "hello.h"
  

  第二处加BEGIN_EXTERN_C()和END_EXTERN_C():
  

#ifdef COMPILE_DL_JANUARY  
BEGIN_EXTERN_C()       ==>添加的
  
ZEND_GET_MODULE(january)
  
END_EXTERN_C()         ==>添加的
  

#endif  

  3、在如下的地方,加入函数名称,可以理解为php要调用的函数的声明:
  

const zend_function_entry january_functions[] = {  
PHP_FE(confirm_january_compiled,    NULL)
/* For testing, remove later. */  
PHP_FE(january_say, NULL)
  
PHP_FE_END
/* Must be the last line in january_functions[] */  
};
  

  4、注意到january.cpp中,它编写了一个函数例子confirm_january_compiled,现在,我们也需要完成january_say的函数实现,它接收来自php的参数,并在函数中调用c++函数。
  

PHP_FUNCTION(january_say)  
{
  

char *arg1 = NULL, *arg2 = NULL;  

int arg1_len, arg2_len;  

int argc = ZEND_NUM_ARGS();  

if(zend_parse_parameters(argc TSRMLS_CC, "ss", &arg1, &arg1_len, &arg2, &arg2_len) == FAILURE)  

return;  
std::
string a = std::string(arg1);  
std::
string b = std::string(arg2);  
std::
string res = hello_joint(a, b);  
RETURN_STRING(res.c_str(), res.length());
  
}
  

  完成这些步骤之后,剩下的工作就少多了。
  要接下去做其他步骤的话,建议先做两个拷贝动作:
  1,新建lib文件夹,将之前制作的libhello.a拷贝到lib里;
  2,新建include文件夹(也可以等到./configure的时候,它会帮你创建这个文件夹),将hello.h头文件拷贝到这里。
  利用php工具,按顺序运行如下四个命令:
  

phpize  
.
/configure  

make  
make install
  

  注:如果中间修改了程序代码什么的,记得要从第一个phpize重新执行来过。
  运行正常的话,january.so会安装到.../lib/php/extensions/no-debug-non-zts-20131226/目录下。
  最后,需要加载january.so,主要是改配置php.ini。如果不知道这个文件在哪的话,你可以在php程序中输出(echo phpinfo())。
  

echo phpinfo()的输出,可以看到指明了php.ini的所在目录。  
Virtual Directory Support => disabled
  
Configuration File (php.ini) Path => /usr/local/etc/php/5.6
  
Loaded Configuration File => /usr/local/etc/php/5.6/php.ini
  

  首先,找到enable_dl,改为On;
  

enable_dl = On         --在php.ini 中开启php动态加载dl  

  再找到有很多extension=xxxxxx.so的地方,添加下面句子,加载动态库,当然也可以在程序中手动加载。
  

extension=january.so    

    在php程序中测试:
  

echo january_say("hello ", "world!");  

    输出:
  

hello world!  




结语
  快过年了,都不能静心的好好写博客了(真的是水平不够,经验有限的极好借口\(^o^)/~),如果有错误的地方,欢迎指正。
  同时,刚开始做的时候,可能会碰到这样那样的问题,希望你最终能顺利完成!当然,如果这篇博客能对你有一点点帮助的话,就更好了.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-429460-1-1.html 上篇帖子: Ajax传递数组 (PHP后台接收) 下篇帖子: CentOS 6.5 编译 PHP-7 报错:undefined reference to `libiconv
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表