如何基于 PHP-X 快速开发一个 PHP 扩展
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的数组。
#include <phpx.h>
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]);
}
}
0x04 编译扩展
编写一个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,内容为:
<?php
var_dump(cpp_test("hello", 3));
执行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实现扩展类、资源、回调函数等更复杂的功能。
如何基于 PHP-X 快速开发一个 PHP 扩展的更多相关文章
- 快速开发一个PHP扩展
快速开发一个PHP扩展 作者:heiyeluren时间:2008-12-5博客:http://blog.csdn.net/heiyeshuwu 本文通过非常快速的方式讲解了如何制作一个PHP 5.2 ...
- 基于django快速开发一个网站(一)
基于django快速开发一个网站(一) * 创建虚拟环境.基于虚拟环境创建django==2.0.0和图片加载库和mysql数据库驱动 1. 创建目录并创建虚拟环境 ╰$ mkdir Cornuco ...
- Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务
Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具:Spr ...
- 使用.NET Core快速开发一个较正规的命令行应用程序
程序员的世界,命令行工具一直是"体验非常友好"的工具,也能自动化完成很多事情,同时还能结合shell来进行某项任务的批处理(脚本).在.NET Core中,命令行应用程序是基础,但 ...
- 如何快速开发一个支持高效、高并发的分布式ID生成器
ID生成器是指能产生不重复ID服务的程序,在后台开发过程中,尤其是分布式服务.微服务程序开发过程中,经常会用到,例如,为用户的每个请求产生一个唯一ID.为每个消息产生一个ID等等,ID生成器也是进行无 ...
- 使用Vue2+webpack+Es6快速开发一个移动端项目,封装属于自己的jsonpAPI和手势响应式组件
导语 最近看到不少使用vue制作的音乐播放器,挺好玩的,本来工作中也经常使用Vue,一起交流学习,好的话点个star哦 本项目特点如下 : 1. 原生js封装自己的跨域请求函数,支持promise调用 ...
- 如何用原生js开发一个Chrome扩展程序
原文地址:How to Build a Simple Chrome Extension in Vanilla JavaScript 开发一个Chrome扩展程序非常简单,只需要使用原生的js就可以完成 ...
- 基于代码生成器的快速开发平台 JEECG
JEECG是一款基于代码生成器的J2EE快速开发平台,开源界“小普元”超越传统商业企业级开发平台.引领新的开发模式(Online Coding模式(在线开发)->代码生成器模式->手工ME ...
- 用 Go 快速开发一个 RESTful API 服务
何时使用单体 RESTful 服务 对于很多初创公司来说,业务的早期我们更应该关注于业务价值的交付,而单体服务具有架构简单,部署简单,开发成本低等优点,可以帮助我们快速实现产品需求.我们在使用单体服务 ...
随机推荐
- 渗透测试-基于白名单执行payload--Compiler
复现亮神课程 0x01 Compiler前言 说明:Microsoft.Workflow.Comiler.exe是.NET Framework默认自带的一个实用工具,用户能够以XOML工作流文件的形式 ...
- UVA10228 A Star not a Tree?
[返回模拟退火略解] 题目描述 一平面上有 nnn 个点 {Ai}\{A_i\}{Ai},求一个点 XXX 使得σ=∑i=1ndis(Ai,X)\sigma=\sum_{i=1}^{n}{dis(A ...
- Twitter-Snowflake:自增ID算法
简介 Twitter 早期用 MySQL 存储数据,随着用户的增长,单一的 MySQL 实例没法承受海量的数据,后来团队就研究如何产生完美的自增ID,以满足两个基本的要求: 每秒能生成几十万条 ID ...
- 百万年薪python之路 -- python2和python3的区别
python2和python3的区别: python2获取的是整数 python3获取的是浮点数 print函数:(Python3中print为一个函数,必须用括号括起来:Python2中print为 ...
- Leetcode(3)无重复字符的最长子串
Leetcode(3)无重复字符的最长子串 [题目表述]: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 第一种方法:暴力 执行用时:996 ms: 内存消耗:12.9MB 效果: ...
- 在Mac OSX上运行Windows应用程序
在Mac OSX中,借助wine,不需要安装虚拟机也可以运行Window应用程序. wine是一个在Linux和UNIX之上的,WIndows3.x和Windows APIs的实现.是运用API转换技 ...
- 不离开Emacs完成简单程序的编辑编译运行(windows或Linux)
(1)打开Emacs (2)建立一个新的程序文件. 执行 C-x C-f, 然后在屏幕的底部出现minibuffer,光标提示你输入文件名称, 文件名称要带上后缀名,如hello.cpp.回车,然后开 ...
- Charles抓包工具的使用(一)
前提:charles的说明 Charles其实是一款代理服务器,通过过将自己设置成系统(电脑或者浏览器)的网络访问代理服务器,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在W ...
- 设计模式(五)Singleton模式
Singleton模式就是确保只生成一个实例的模式.这里有两个意思,即想确保任何情况下都绝对只有一个实例和想在程序上表现出“只存在一个实例”. 下面通过一个实例来说明这种设计模式. package B ...
- unity UI事件
由于工作需要到持续按键,所以了解了一下unity UI事件,本文主要转载于http://www.cnblogs.com/zou90512/p/3995932.html?utm_source=tuico ...