书接上文,如果要是想编译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
- 先将
edutest3.c
重命名为edutest3.cc
,让编译可以编译C++。 - 修改
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
。
- 在
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类(完全从国外的代码里抄来的例子,以后再修改成自己的),我们将实现和头文件分开放置:
- 实现
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 }
- 头文件
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%