美文网首页php-learning
PHP的C/C++扩展(二)

PHP的C/C++扩展(二)

作者: 程序员_张雪峰 | 来源:发表于2016-08-01 14:39 被阅读143次

    书接上文,如果要是想编译C++而不是纯C语言的代码,还需要做一些必要的修改。

    一、我们用上文中的步骤,运行命令./ext_skel--extname=edutest3,创建edutest3。

     zhangxuefeng@zhangxuefengs-MacBook-Pro  ~/Developer/php-5.6.24/ext/edutest3  ll
    total 56
    -rw-r--r--  1 zhangxuefeng  staff     9B Aug  1 11:23 CREDITS
    -rw-r--r--  1 zhangxuefeng  staff     0B Aug  1 11:23 EXPERIMENTAL
    -rw-r--r--  1 zhangxuefeng  staff   2.1K Aug  1 11:23 config.m4
    -rw-r--r--  1 zhangxuefeng  staff   310B Aug  1 11:23 config.w32
    -rw-r--r--  1 zhangxuefeng  staff   5.0K Aug  1 11:23 edutest3.c
    -rw-r--r--  1 zhangxuefeng  staff   508B Aug  1 11:23 edutest3.php
    -rw-r--r--  1 zhangxuefeng  staff   2.6K Aug  1 11:23 php_edutest3.h
    drwxr-xr-x  3 zhangxuefeng  staff   102B Aug  1 11:23 tests
    
    1. 先将edutest3.c重命名为edutest3.cc,让编译可以编译C++。
    2. 修改config.m4,除了上文中说到的内容,还需要修改修改文件名,这里我们在添加一个想要一起编译的代码文件:
     59   PHP_REQUIRE_CXX()
     60   PHP_SUBST(EDUTEST3_SHARED_LIBADD)
     61   PHP_ADD_LIBRARY(stdc++, 1, EDUTEST3_SHARED_LIBADD)
     62   PHP_NEW_EXTENSION(edutest3, edutest3.cc wenku.cc, $ext_shared)
    

    简要说明:
    59行,要求系统使用C++编译器。
    61行,引入C++标准库libstdc++
    62行,重命名成.cc文件,并添加一个wenku.cc

    1. php_edutest3.h,添加一些信息和头文件:
     27 #define PHP_EDUTEST3_EXTNAME "edutest3"
     28 #define PHP_EDUTEST3_VERSION "0.1.0" /* Replace with version number for your extension */
     29
     30 #ifdef HAVE_CONFIG_H
     31 #include "config.h"
     32 #endif
     33
     34 extern "C" {
     35 #include "php.h"
     36 }
    

    二、创建wenku类(完全从国外的代码里抄来的例子,以后再修改成自己的),我们将实现和头文件分开放置:

    1. 实现wenku.cc:
      1 #include "wenku.h"
      2
      3 Wenku::Wenku(int maxGear) {
      4     this->maxGear = maxGear;
      5     this->currentGear = 1;
      6     this->speed = 0;
      7 }
      8
      9 void Wenku::shift(int gear) {
     10     if (gear < 1 || gear > maxGear) {
     11         return;
     12     }
     13     currentGear = gear;
     14 }
     15
     16 void Wenku::accelerate() {
     17     speed += (5 * this->getCurrentGear());
     18 }
     19
     20 void Wenku::brake() {
     21     speed -= (5 * this->getCurrentGear());
     22 }
     23
     24 int Wenku::getCurrentSpeed() {
     25     return speed;
     26 }
     27
     28 int Wenku::getCurrentGear() {
     29     return currentGear;
     30 }
    
    1. 头文件wenku.h
      1 #ifndef EDUTEST3_WENKU_H
      2 #define EDUTEST3_WENKU_H
      3
      4 // A very simple wenku class
      5 class Wenku {
      6 public:
      7     Wenku(int maxGear);
      8     void shift(int gear);
      9     void accelerate();
     10     void brake();
     11     int getCurrentSpeed();
     12     int getCurrentGear();
     13 private:
     14     int maxGear;
     15     int currentGear;
     16     int speed;
     17 };
     18
     19 #endif /* EDUTEST3_WENKU_H */
    

    三、修改主文件edutest3.cc,将上面类中的函数声明进来、头文件引入,使PHP运行时会初始化:

     21 #ifdef HAVE_CONFIG_H
     22 #include "config.h"
     23 #endif
     24
     25 #include "php.h"
     26 #include "php_ini.h"
     27 #include "ext/standard/info.h"
     28 #include "php_edutest3.h"
     29 #include "wenku.h"
    ……
     38 zend_object_handlers wenku_object_handlers;
     39
     40 struct wenku_object {
     41     zend_object std;
     42     Wenku *wenku;
     43 };
     44
     45 zend_class_entry *wenku_ce;
     46
     47 void wenku_free_storage(void *object TSRMLS_DC)
     48 {
     49     wenku_object *obj = (wenku_object *)object;
     50     delete obj->wenku;
     51
     52     zend_hash_destroy(obj->std.properties);
     53     FREE_HASHTABLE(obj->std.properties);
     54
     55     efree(obj);
     56 }
     57
     58 zend_object_value wenku_create_handler(zend_class_entry *type TSRMLS_DC)
     59 {
     60     zval *tmp;
     61     zend_object_value retval;
     62
     63     wenku_object *obj = (wenku_object *)emalloc(sizeof(wenku_object));
     64     memset(obj, 0, sizeof(wenku_object));
     65     obj->std.ce = type;
     66
     67     ALLOC_HASHTABLE(obj->std.properties);
     68     zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
     69     //zend_hash_copy(obj->std.properties, &type->default_properties, (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
     70     object_properties_init(&obj->std, type);
     71
     72     retval.handle = zend_objects_store_put(obj, NULL, wenku_free_storage, NULL TSRMLS_CC);
     73     retval.handlers = &wenku_object_handlers;
     74
     75     return retval;
     76 }
     77
     78
     79 PHP_METHOD(Wenku, __construct)
     80 {
     81     long maxGear;
     82     Wenku *wenku = NULL;
     83     zval *object = getThis();
     84
     85     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxGear) == FAILURE) {
     86         RETURN_NULL();
     87     }
     88
     89     wenku = new Wenku(maxGear);
     90     wenku_object *obj = (wenku_object *)zend_object_store_get_object(object TSRMLS_CC);
     91     obj->wenku = wenku;
     92 }
     93 PHP_METHOD(Wenku, p_shift)
     94 {
     95     long gear;
     96
     97     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gear) == FAILURE) {
     98         RETURN_NULL();
     99     }
    100
    101     Wenku *wenku;
    102     wenku_object *obj = (wenku_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
    103     wenku = obj->wenku;
    104     if (wenku != NULL) {
    105         wenku->shift(gear);
    106     }
    107 }
    108 PHP_METHOD(Wenku, p_accelerate)
    109 {
    110     Wenku *wenku;
    111     wenku_object *obj = (wenku_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
    112     wenku = obj->wenku;
    113     if (wenku != NULL) {
    114         wenku->accelerate();
    115     }
    116 }
    117 PHP_METHOD(Wenku, p_brake)
    118 {
    119     Wenku *wenku;
    120     wenku_object *obj = (wenku_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
    121     wenku = obj->wenku;
    122     if (wenku != NULL) {
    123         wenku->brake();
    124     }
    125 }
    126 PHP_METHOD(Wenku, p_getCurrentSpeed)
    127 {
    128     Wenku *wenku;
    129     wenku_object *obj = (wenku_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
    130     wenku = obj->wenku;
    131     if (wenku != NULL) {
    132         RETURN_LONG(wenku->getCurrentSpeed());
    133     }
    134     RETURN_NULL();
    135 }
    136 PHP_METHOD(Wenku, p_getCurrentGear)
    137 {
    138     Wenku *wenku;
    139     wenku_object *obj = (wenku_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
    140     wenku = obj->wenku;
    141     if (wenku != NULL) {
    142         RETURN_LONG(wenku->getCurrentGear());
    143     }
    144     RETURN_NULL();
    145 }
    146
    147 zend_function_entry wenku_methods[] = {
    148     PHP_ME(Wenku,  __construct,     NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    149     PHP_ME(Wenku,  p_shift,           NULL, ZEND_ACC_PUBLIC)
    150     PHP_ME(Wenku,  p_accelerate,      NULL, ZEND_ACC_PUBLIC)
    151     PHP_ME(Wenku,  p_brake,           NULL, ZEND_ACC_PUBLIC)
    152     PHP_ME(Wenku,  p_getCurrentSpeed, NULL, ZEND_ACC_PUBLIC)
    153     PHP_ME(Wenku,  p_getCurrentGear,  NULL, ZEND_ACC_PUBLIC)
    154     {NULL, NULL, NULL}
    155 };
    156
    

    四、在模块初始化方法中注册wenku类:

    206 /* {{{ PHP_MINIT_FUNCTION
    207  */
    208 PHP_MINIT_FUNCTION(edutest4)
    209 {
    210         /* If you have INI entries, uncomment these lines
    211         REGISTER_INI_ENTRIES();
    212         */
    213         zend_class_entry ce;
    214         INIT_CLASS_ENTRY(ce, "Wenku", wenku_methods);
    215         wenku_ce = zend_register_internal_class(&ce TSRMLS_CC);
    216         wenku_ce->create_object = wenku_create_handler;
    217         memcpy(&wenku_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    218         wenku_object_handlers.clone_obj = NULL;
    219         return SUCCESS;
    220 }
    

    PHP_MINIT_FUNCTION()函数的简要说明:
    当HTTP服务启动的时候,它就启动PHP的解释器。PHP会调用每一个扩展的MINIT函数,可以通过查看php.ini文件来看哪些扩展模块是激活的。MINIT就是Module Initialization,即模块初始化方法的简称,在每一个模块初始化方法里,会定义并初始化一系列在以后的页面请求中需要用到的函数、类、变量等。

    *没看懂上面代码的同学可以先这么干,后续我再补充相关说明。 *

    五、配置、编译、安装,只需要按照上文所述步骤进行即可。

    六、编写一个PHP的测试脚本:

      1 <?php
      2 // create a 5 gear wenku
      3 $wenku = new Wenku(5);
      4 print $wenku->p_getCurrentSpeed(); // prints '0'
      5 echo "\n";
      6 $wenku->p_accelerate();
      7 print $wenku->p_getCurrentSpeed(); // prints '5'
    

    输出结果0、5正确:

     zhangxuefeng@zhangxuefengs-MacBook-Pro  ~/Developer  php wenku-cpp.php
    0
    5%
    

    相关文章

      网友评论

        本文标题:PHP的C/C++扩展(二)

        本文链接:https://www.haomeiwen.com/subject/fymxsttx.html