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

书接上文,如果要是想编译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%
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容