设为首页 加入收藏

TOP

PHP扩展调用C++静态库(一)
2017-10-13 10:23:22 】 浏览:3529
Tags:PHP 扩展 调用 静态

概述

      php通过扩展方式,调用c++源码,这样做的理由有很多,当你搜到这篇文章时,相信你已经有自己的考虑了。

写这篇博客的理由有二:

  1. 整理下php扩展调用c++代码的过程。嗯,对,网上有很多类似的文章,不过对于php扩展c++的方式,很多文章在关键的地方并没有说明,或者说,大部分都是扩展调用c代码的。
  2. 已经两年有余没写博客了,在这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;
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++ 头文件系列(forward_list) 下一篇【51NOD】1006 最长公共子序列Lcs..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目