如何基于 PHP-X 快速开发一个 PHP 扩展

摘要:
0x01 StartPHP-X是基于C++11开发的,并使用cmake进行编译和配置。包括:gcc-4.8或更高版本,PHP 7.0或更高。您需要php7-dev开发工具包cmake-2.8或更高版本,然后安装PHPX。PHPX_EXTENSION(){EXTENSION*ext=newExtension;returnext;}此处必须使用newExtension,而不是直接在堆栈上创建对象0x03。添加函数。PHP扩展的主要功能是提供扩展功能。因为扩展函数是用C/C++代码实现的,所以它们的性能将比PHP用户函数高几十倍甚至数百倍。祝贺现在您已经成功开发了一个PHP扩展。要在实际项目中真正使用PHP-X,还有很多工作要做。

0x01 起步

PHP-X本身基于C++11开发,使用cmake进行编译配置。首先,你需要确定所有依赖项已安装好。包括:

  • gcc-4.8 或更高版本
  • PHP7.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 新建工程

使用任意开发工具,新建一个http://test.cc源文件。首先需要引入phpx.h头文件。然后使用using引入phpx的命名空间。PHP官方未使用C++,因此phpx直接使用了php作为命名空间。

#include <phpx.h>
using 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;
}
这里必须使用 new Extension,而不能直接在栈上创建对象

0x03 增加函数

一个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的数组。

 1 #include <phpx.h>
 2 using namespace std;
 3 using namespace php;
 4 
 5 //声明函数
 6 PHPX_FUNCTION(cpp_test);
 7 
 8 PHPX_EXTENSION()
 9 {
10     Extension *ext = new Extension("test", "0.0.1");
11     ext->registerFunction(PHPX_FN(cpp_test));
12     return ext;
13 }
14 
15 //实现函数
16 PHPX_FUNCTION(cpp_test)
17 {
18     //args[1] 就是这个扩展函数的第 2 个参数
19     long n = args[1].toInt();
20     
21     //将返回值 retval 初始化为数组
22     Array _array(retval);
23     
24     for(int i = 0; i < n; i++)
25     {
26         //args[0] 就是这个扩展函数的第 1 个参数
27         //append 方法表示向数组中追加元素
28         _array.append(args[0]);
29     }
30 }

0x04 编译扩展

编写一个Makefile文件。内容如下:

 1 PHP_INCLUDE = `php-config --includes`
 2 PHP_LIBS = `php-config --libs`
 3 PHP_LDFLAGS = `php-config --ldflags`
 4 PHP_INCLUDE_DIR = `php-config --include-dir`
 5 PHP_EXTENSION_DIR = `php-config --extension-dir`
 6 
 7 test.so: test.cc
 8     c++ -DHAVE_CONFIG_H -g -o test.so -O0 -fPIC -shared test.cc -std=c++11 ${PHP_INCLUDE} -I${PHP_INCLUDE_DIR} -lphpx
 9     
10 install: test.so
11     cp test.so ${PHP_EXTENSION_DIR}/
12 clean:
13     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来观察你的扩展是否正常加载。

 1 php -m
 2 [PHP Modules]
 3 Core
 4 ctype
 5 curl
 6 date
 7 dom
 8 fileinfo
 9 filter
10 gd
11 hash
12 iconv
13 inotify
14 json
15 libxml
16 mbstring
17 mcrypt
18 memcached
19 mongodb
20 mysqli
21 mysqlnd
22 openssl
23 pcntl
24 pcre
25 PDO
26 pdo_mysql
27 pdo_sqlite
28 Phar
29 posix
30 redis
31 Reflection
32 session
33 SimpleXML
34 sockets
35 SPL
36 sqlite3
37 standard
38 swoole
39 test
40 tokenizer
41 xml
42 xmlreader
43 xmlwriter
44 yac
45 zlib
46 zmq
47 
48 [Zend Modules]

这里看到test,表明你的扩展已经加载成功了,现在就可以调用cpp_test这个扩展函数了。

0x05 执行

编写一个test.php,内容为:

 1 <?php
 2 var_dump(cpp_test("hello", 3));
 3 执行test.php:
 4 
 5 php test.php
 6 array(3) {
 7   [0]=>
 8   string(5) "hello"
 9   [1]=>
10   string(5) "hello"
11   [2]=>
12   string(5) "hello"
13 }

可以看到执行结果符合预期。那么恭喜你,现在你已经成功地开发了一个PHP扩展了。是不是很简单?

0x06 更多

上面的例子还比较简单,只是编写了一个扩展函数。要真正在实际项目中使用PHP-X你还有很多工作要做。

  • 需要C++的功底
  • 了解更多PHP-X的 API

另外配合使用Eclipse等IDE工具,可以实现API自动提示和补齐,开发起来会更顺手。

相比Zend API,PHP-X要简单易用地多了,相信你不会花太多时间就可以掌握此项技能。在接下来我会撰写更多教程,教大家如何使用PHP-X实现扩展类、资源、回调函数等更复杂的功能。

免责声明:文章转载自《如何基于 PHP-X 快速开发一个 PHP 扩展》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇HDU-2647 Reward(链式前向星+拓扑排序)安卓的设备的分辨率下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mysql和Oracle在对clob和blob字段的处理

一、MySQL与Oracle数据库如何处理Clob,Blob数据类型 (1)不通数据库中对应clob,blob的类型如下: MySQL中:clob对应text,blob对应blob DB2/Oracle中:clob对应clob,blob对应blob (2)domain中对应的类型: clob对应String,blob对应byte[] clob对应ja...

php全面获取url地址栏及各种参数

  php教程 全面获取url地址栏参数多种方法:$_SERVER["SERVER_PORT"]//获取端口$_SERVER['HTTP_HOST']//获取域名或主机地址$_SERVER['SERVER_NAME']//获取域名或主机地php://input是什么意思?php输入流input的介绍址 注:只是主域名 如xhxu.cn$_SERVER["R...

MySQL 千万 级数据量根据(索引)优化 查询 速度

一、索引的作用索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让人难以忍受了。 提升查询速度的方向一是提升硬件(内存、cpu、硬盘),二是在软件上优化(加索引、优化sql;优化sql不在本文阐述范围之内)。 能在软件上解决的...

解决 Java FileNotFoundException

解决 Java FileNotFoundException 异常 1、错误场景  _| src     _| cn.itcod      _| test      _| inflection      _| inflectionTest.java      _| application.txt package cn.itcod.test.inflectio...

Mac下PHP开发环境的搭建(转载)

一、首先Mac OS自带Apache,只需要启动Apache就行。 打开终端,输入命令:sudo apachectl start : 介绍几个Apache的常用命令 //启动Apache服务 sudoapachectl start //重启Apache服务 sudoapachectl restart //停止Apache服务 sudoapach...

MySQL 新建用户,为用户授权,指定用户访问数据库

1.登录MySQL mysql -u root -p 2.添加新用户(允许所有ip访问) create user 'test'@'%' identified by '123456'; #test:用户名,%:所有ip地址,123456:密码 3.创建数据库 CREATE DATABASE test_db DEFAULT CHARSET utf8mb4...