摘要:这里看到,表明你的扩展已经加载成功了,现在就可以调用这个扩展函数了。是不是很简单更多上面的例子还比较简单,只是编写了一个扩展函数。
PHP-X是我在2017年年初创建的一个新项目。这个项目的目标就是让有一定工作经验的PHP程序都能够具备扩展开发的能力。
0x00 初衷从2012年开始编写swoole,现在算来已经有5个年头了。我发现编写一个 PHP 扩展这个工作非常艰难。PHP 程序员群体中,甚至可以说 100 人中都很难找出一个会编写 PHP 扩展的人来。PHP 官方对扩展开发者非常不友好,源代码中提供的Zend API极其难用,API复杂而且凌乱,充斥着各种宏的写法。Zend API坑非常多,普通开发者很容易踩到坑里。出现各种莫名其妙的core dump问题。Zend API几乎没有任何文档,开发者如果要真正掌握这项技能需要付出大量的学习时间。
于是我今年就冒出一个新的想法,基于我编写swoole扩展超过5年的经验,我试图在Zend API和C++之间建立一个包装层,让PHP扩展开发变得简单。有一定C++基础的PHPer都可以轻松得开发一个PHP扩展。
PHP-X这个项目就这样诞生了,开发只用了一个月的时间。它的开发效率非常高,在我公司中一个只工作了3年的 PHP 程序员,都可以做出一个扩展来。接下来陆续在公司的几个项目中进行了快速验证。在3个的时间里修复了大量崩溃和内存泄漏问题。目前稳定性、性能、健壮性均已达到工业级水准。
0x01 起步PHP-X本身基于C++11开发,使用cmake进行编译配置。首先,你需要确定所有依赖项已安装好。包括:
gcc-4.8 或更高版本
php-7.0 或更高版本,需要php7-dev包
cmake-2.8 或更高版本
然后安装PHP-X。
git clone https://github.com/swoole/PHP-X.git cd PHP-X cmake . make -j 4 sudo make install
未出现任何编译错误,会成功编译出libphpx.so,并安装到系统的lib目录。头文件会复制到系统的include目录。这时需要执行 sudo ldconfig刷新so文件缓存。
0x02 新建工程使用任意开发工具,新建一个test.cc源文件。首先需要引入phpx.h头文件。然后使用using引入phpx的命名空间。PHP官方未使用C++,因此phpx直接使用了php作为命名空间。
#includeusing namespace std; using namespace php;
创建扩展使用PHPX_EXTENSION宏来实现。在这宏中只需要new Extension即可创建扩展。构造方法接受2个参数,第一个是扩展的名称,第二个是扩展的版本号。在PHPX_EXTENSION宏中return这个扩展对象的指针。
PHPX_EXTENSION() { Extension *ext = new Extension("test", "0.0.1"); return ext; }
0x03 增加函数这里必须使用 new Extension,而不能直接在栈上创建对象
一个PHP扩展的主要作用就是提供扩展函数,扩展函数由于是用C/C++代码实现,因此它的性能会比PHP用户函数性能高几十甚至上百倍。在phpx中实现函数非常简单。使用PHPX_FUNCTION来实现扩展函数,然后调用Extension::registerFunction来注册扩展函数。
PHPX_FN是一个助手宏,实际上展开就是"cpp_hello_world", cpp_hello_world
PHPX_FUNCTION展开后,包含了2个变量,第一个是参数args,第二个是返回值retval
通过操作args和retval两个变量,就可以实现函数的输入和输出
这里我们的代码非常简单,cpp_test($str, $n),调用这个函数返回一个$n个$str的数组。
#include0x04 编译扩展using namespace std; using namespace php; //声明函数 PHPX_FUNCTION(cpp_test); PHPX_EXTENSION() { Extension *ext = new Extension("test", "0.0.1"); ext->registerFunction(PHPX_FN(cpp_test)); return ext; } //实现函数 PHPX_FUNCTION(cpp_test) { //args[1] 就是这个扩展函数的第 2 个参数 long n = args[1].toInt(); //将返回值 retval 初始化为数组 Array _array(retval); for(int i = 0; i < n; i++) { //args[0] 就是这个扩展函数的第 1 个参数 //append 方法表示向数组中追加元素 _array.append(args[0]); } }
编写一个Makefile文件。内容如下:
PHP_INCLUDE = `php-config --includes` PHP_LIBS = `php-config --libs` PHP_LDFLAGS = `php-config --ldflags` PHP_INCLUDE_DIR = `php-config --include-dir` PHP_EXTENSION_DIR = `php-config --extension-dir` test.so: test.cc c++ -DHAVE_CONFIG_H -g -o test.so -O0 -fPIC -shared test.cc -std=c++11 ${PHP_INCLUDE} -I${PHP_INCLUDE_DIR} -lphpx install: test.so cp test.so ${PHP_EXTENSION_DIR}/ clean: rm *.so
php-config 这个工具是PHP提供的,使用php-config可以得到PHP的安装路径、头文件目录、扩展目录、其他额外的编译参数等等。
这个Makefile支持了3个指令,make编译,make clean清理,make install安装到扩展目录中。
这里可能需要root权限,使用sudo make install进行安装
直接从网页复制,可能会出现tab制表符被替换为空格,请手工编辑一下Makefile使用tab缩进
MacOS下需要在c++编译参数中增加-undefined dynamic_lookup
编写好之后执行make install,就会编译扩展并将扩展test.so安装到PHP的扩展目录中。这时需要修改php.ini加入extension=test.so加载扩展。
使用php -m来观察你的扩展是否正常加载。
php -m [PHP Modules] Core ctype curl date dom fileinfo filter gd hash iconv inotify json libxml mbstring mcrypt memcached mongodb mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql pdo_sqlite Phar posix redis Reflection session SimpleXML sockets SPL sqlite3 standard swoole test tokenizer xml xmlreader xmlwriter yac zlib zmq [Zend Modules]
这里看到test,表明你的扩展已经加载成功了,现在就可以调用cpp_test这个扩展函数了。
0x05 执行编写一个test.php,内容为:
执行test.php:
php test.php array(3) { [0]=> string(5) "hello" [1]=> string(5) "hello" [2]=> string(5) "hello" }可以看到执行结果符合预期。那么恭喜你,现在你已经成功地开发了一个PHP扩展了。是不是很简单?
0x06 更多上面的例子还比较简单,只是编写了一个扩展函数。要真正在实际项目中使用PHP-X你还有很多工作要做。
需要C++的功底
了解更多PHP-X的 API
另外配合使用Eclipse等IDE工具,可以实现API自动提示和补齐,开发起来会更顺手。
相比Zend API,PHP-X要简单易用地多了,相信你不会花太多时间就可以掌握此项技能。在接下来我会撰写更多教程,教大家如何使用PHP-X实现扩展类、资源、回调函数等更复杂的功能。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/25808.html
摘要:四使用语言开发是我重点推荐的扩展开发框架,简明易懂,功能强大,开发效率高,代码易维护,执行速度快。优点三支持,的扩展开发有两套扩展开发框架,分别支持,,虽然框架代码有两个,但是接口却是一样的。 PHP扩展是高级PHP程序员必须了解的技能之一,对于一个初入门的PHP扩展开发者,怎么才能开发一个成熟的扩展,进入PHP开发的高级领域呢?本系列开发教程将手把手带您从入门进入高级阶段。本教程系列...
摘要:接着上一篇文章,本文开始在扩展内实现类的定义和对象操作。因此定义类,需要在的回调中进行。使用类名方法名即可。连接成功连接失败在中不仅可以创建扩展内置的类,还可以创建代码定义的类。 接着上一篇文章,本文开始在扩展内实现类的定义和对象操作。基于PHP-X提供的封装,使用C++语言可以轻松地实现一个PHP的类,还可以在C++代码中创建任意PHP对象,调用对象方法、读写对象的属性。 0x00 ...
摘要:本文主要介绍内置函数的使用,在扩展开发中,会经常用到这些内置函数,的封装,使得调用这些函数像代码一样简单。的使用方法与语言的是完全一致的。包括的超全局变量和其他代码使用关键词声明的全局变量。 本文主要介绍PHP-X内置函数的使用,在PHP扩展开发中,会经常用到这些内置函数,PHP-X的封装,使得调用这些函数像PHP代码一样简单。 echo 在扩展中需要输出一些内容,可以使用echo函数...
摘要:总得来说,从大三开始到入职奇虎这年,一直处于自己探索阶段,各种折腾,浪费了不少青春,收获总得来说不是很大。入职奇虎之后,有了一份稳定的工作,从此一天当作两天来用,恶补我之前浪费的青春。 经过紧张的开发,我终于费了九牛二虎之力将 zendAPI 的项目官网做好上线了,眨眼已经入职奇虎一年了,我也走完了我的职业生涯规划的第一年,别问我之前4年干啥去了,我去潇洒了 (拉着几个大学同学创业去了...
摘要:项目是什么是对的接口使用的最新标准进行而面向对象的封装,从而屏蔽了底层的接口复杂性,加快开发扩展的效率。国内同类型的项目推荐目前国内有一个跟比较类似的项目,这个项目是项目作者开发,值得推荐。项目名字项目的地址是大家有兴趣可以研究。 项目Logo showImg(https://segmentfault.com/img/bVVtW8?w=716&h=218); zendAPI 是什么? ...
阅读 2337·2021-11-15 11:38
阅读 3545·2021-09-22 15:16
阅读 1187·2021-09-10 11:11
阅读 3159·2021-09-10 10:51
阅读 2922·2019-08-30 15:56
阅读 2776·2019-08-30 15:44
阅读 3188·2019-08-28 18:28
阅读 3527·2019-08-26 13:36