使用c++11开发php7扩展(韩天峰)
简单说就是天峰在多年的php扩展开发中,感受到基于c的zend api十分不方便,所以基于c++11对zend api进行了封装,既降低了php扩展的开发难度,提高了开发效率,同时也为php带了更多的想象空间,并把这个项目命名为php-x
什么是php扩展?
定义
php本身是c语言开发的,其实可以想象我们是使用php这个高级语言去驱动一个c开发的引擎(zend engine)去做事情的。php扩展就是允许我们使用c为整个引擎开发新的插件来扩展php的功能,比如网络请求的curl扩展,使用mysql的mysqli扩展等。这种机制有利于社区为php的发展添砖加瓦,可以说zend engine本身就是一个个插件堆积出来的
如何开发扩展?
- 使用ext_skel生成扩展开发骨架
- 编辑config.m4文件
- 在extension.h头文件中定义扩展函数
- 修改extension.c源文件,实现扩展函数逻辑
- 利用phpize configure make & make install安装扩展
这样当php程序中调用扩展函数时,zend引擎会去调用你所开发的扩展。当然,你在扩展逻辑中只能使用c语言通过zend api来对传入的php变量进行解析、处理,最终再通过zend api返回php变量,继续原流程
目前扩展开发有何痛点?
zend api不好用
- 大量使用宏
- api名称太长,参数太多,容易出错
- api分散在众多.h和.c文件中
- 需要精通c语言,大量的指针场景,容易出错
- 没有任何,任何的教程或手册!
古老的c语言
- 50年历史的古老编程语言
- 面向过程的风格,封装性差
- 指针容易出错
- 缺少原生的数据结构支持
- 仅适合编写底层软件
php-x做了哪些工作?
鉴于前面说的问题,php-x使用c++11对zend api进行了封装,选择c++11是因为
- c++是现代编程语言
- 面向对象风格,封装性好
- 模板泛型编程
- STL容器
- 通用编程,适用范围广
可以简单对比一下封装后的代码
// 变量操作
ZVAL_LONG(&a, 1234); // zend api
Variant a = 1234; // php-x
// 类型推断
Z_TYPE_P(value) == IS_LONG; // zend api
value.isLong(); // php-x
// 类型转换
convert_to_long(value); // zend api
value.toInt() // php-x
此外,php-x还提供了数组、字典、资源等多种常见数据结构和方法封装。而且还提供了在c++中嵌套php的功能
,c++中也可以访问诸如$_GET、$_POST等上下文,配合通过php扩展赋予了php调用c++的能力,实际上php-x完全打通了php与c++
实战php7扩展
本小节利用php-x实现一个扩展my_ext,包含my_ext_class类和my_ext_test函数,对php-x开发php7扩展做一个简单的示例
php7扩展注册
PHPX_EXTENSION() {
Extension *extension = new Extension("my_ext", "0.0.1");
extension->onStart = [extension]() {
extension->registerConstant("MY_EXT_VERSION", "0.0.1");
extension->registerClass(my_ext_class);
};
extension->registerFunction(PHPX_FN(my_ext_test));
return extension;
}
实现扩展函数
PHPX_FUNCTION(my_ext_test) {
for (int i = 0; i < args.count(); i++) {
php::echo("arg[%d] type is %d\n", i, args[i].type());
}
Variant v1 = arg[0];
Array arr(v1);
arr.set(1, 'efg');
retval = arr;
}
实现扩展类
Class *my_ext_class = new Class('myClass');
my_ext_class->addMethod(PHPX_ME(myClass, test), STATIC);
my_ext_class->addMethod(PHPX_ME(myClass, test2));
my_ext_class->addProperty('name', 'Rango');
extension->registerClass(my_ext_class);
实现类方法
PHPX_METHOND(myClass, test2) {
Variant res = newResource('String', new String('hello'));
_this.set('resource', res);
php::error(E_WARNING, 'err message');
}
注册phpinfo
extension->info({'gtk support', 'enabled'}, {
{'author', 'Rango'},
{'version', ext->version},
});
然后和一般扩展一样编译安装就行
php的想象空间
php-x打通了php与c++,理论上c++可以做的事,php同样也能做到。同时php扩展的开发难度也大大降低,可以应用于更多的场景
- 可以用c++扩展实现多线程
- 程序中计算密集型部分可以轻松使用扩展实现
- 可以通过扩展加密商业软件
- Fackbook、Google、Microsoft、Tencent等巨头的开源c++库可以为php所用了
网友评论