β

使用PHP-CPP开发PHP扩展

Mindy 89 阅读



传统的PHP扩展开发比较麻烦,需要对Zend引擎和指针操作相当熟练,所以衍生出两种比较常用的开发工具。PHP-CPP其中之一,另一个是Zephir。这里我打算只介绍PHP-CPP。原因主要也是我本身就是C++出生,介绍起来会更得心应手。安装和配置使用git可以在任何时刻获取最新版本的PHP-CPP。de  >git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.gitde>

PHP-CPP采用 C++11 编写,因此老的编译器是无法使用的。g++的话必须更新到4.8以上的版本。(我现在使用的Ubuntu14.04.3已经是g++4.8.4了,如果使用其他平台开发请参考对应的文档)此外,开发中还需要php.h,在ubuntu下,我们可以通过

de  >sudo apt-get install php5-devde>

来方便获取到php的开发包。如果提示缺少依赖,可以尝试更换Ubuntu的软件源然后执行de >sudo apt-get updatede>再试。(我用的是Aliyun的)

接下来,我们需要把clone回来的github源码进行编译。

de  >cd PHP-CPP
make && sudo make installde>

这将会编译出libphpcpp.so,并copy到/us/lib下。然后其他suoyou 的PHP-CPP头文件被copy到/usr/include和/usr/include/phpcpp目录下。

经过上面几个简单步骤,开发环境的安装就完成了。

脚手架

官方提供了一个 脚手架代码 ,这个代码包含了三个文件:de >main.cppde>,de >Makefilede>,de >yourextension.inide>。

  • de >main.cppde>:包含了get_module函数的入口程序文件
  • de >Makefilede>:make文件
  • de >yourextension.inide>:包含了加载扩展的配置代码

Makefile

如果你对make不熟,也不用担心。这里不会用到很高深的make配置。(要知道,讨论make可以写整整一本书,我现在都还没有特别了解make的所有功能)只需要简单像下面改一些参数即可。

  • de >NAME = yourextensionde> 可以改成自己扩展的名字
  • de >INI_DIR = /etc/php5/conf.dde>。这里是你系统中PHP配置文件的位置。在我的Ubuntu14.04中,这个路径是de >/etc/php5/cli/conf.dde>。

除了上述两个地方,其他地方保留原装即可。

yourextension.ini

这个文件可以重命名为自己扩展的名字。例如我可以改为de >extension=myfirstextension.sode>

main.cpp

这个文件才是重点,它不像普通C程序那样入口是main函数,而是以一个get_module函数作为核心。


#include <phpcpp.h>

/**
* tell the compiler that the get_module is a pure C function
*/
extern "C" {

/**
* Function that is called by PHP right after the PHP process
* has started, and that returns an address of an internal PHP
* strucure with all the details and features of your extension
*
* @return void* a pointer to an address that is understood by PHP
*/
PHPCPP_EXPORT void *get_module()
{
// static(!) Php::Extension object that should stay in memory
// for the entire duration of the process (that's why it's static)
static Php::Extension extension("yourextension", "1.0");

// @todo add your own functions, classes, namespaces to the extension

// return the extension
return extension;
}
}




尽管没有main函数,但是PHP在加载扩展之前会调用这个函数,因此它可以看成是PHP扩展程序的入口。我们注意到这个函数用de >extern Cde>修饰过,这是来自C++的关键字,意义在于希望在C++中使用其他语言(这里主要指C语言)所编写的函数,或者希望C++链接出来的函数可以在其他语言中使用。
提到这里,不得不先简单描述一下PHP载入扩展的过程。我们知道,PHP的扩展要么是de >.sode>文件,要么是de >.dllde>文件,取决于所处的操作系统(Linux或者Windows)。当PHP进程启动的时候,它会先载入de >*.inide>配置文件,通过de >extension=name.sode>来读取每一个扩展。读取方式就是加载这些文件中的de >get_module()de>函数。(这里不赘述Linux和Windows动态链接的原理,只需要知道PHP运行的时候会从扩展文件中调用指定函数即可)这个de >get_module()de>函数必须返回一个指针。这个指针指向的地址空间包含了扩展中定义的所有类,函数,变量和常量。Zend引擎的官方文档并没有很好地解释这个指针的数据结构。而这正式PHP-CPP要做的——它封装并简化了原有的Zend的API,让开发者可以专注于开发PHP扩展。
好了,现在我们可以解释为什么这里我们用到了de >extern Cde>声明了,PHP希望你的扩展,尤其是de >get_module()de>函数是用C实现的,而PHP-CPP需要用到C++的特性,所以必须用这个声明告诉编译器这是C函数,这样才可以避免C++的名字改编(Name Mangling)——什么是名字改编?简单说主要是为了实现C++的重载函数功能而在编译阶段把函数名字进行适当重写,详细内容可以查阅相关书籍或者资料,这里不再赘述。
另外,PHP-CPP还定义了一个叫做de >PHPCPP_EXPORTde>的宏,主要用于导出de >get_module()de>函数,这个宏的具体实现取决于不同的操作系统——在Windows和Linux中实现动态链接的方法是不一样的,这个在上文中也有提到。而这个宏,也是PHP-CPP唯一会用到的宏。(熟悉C或者C++编程的读者可能会对这句话深有感触——一些平台的API和框架大量使用了宏去实现一些原有C++没有的特性,但是却导致了理解灾难)
在脚手架的代码中,我们注意到de >get_module()de>函数只有两行代码,一行是

C++
de  >static Php::Extension extension("yourextension", "1.0");
de>

这里Php::Extension是我们扩展的核心类,注意到我们用static修饰它主要是因为这个对象是全局存在的,不局限于de >get_module()de>本身。构造函数接受两个参数——扩展名字和版本号。
第二行代码——我们只是简单地返回了上面声明的对象。对C++比较熟悉的人可能会觉得奇怪——为什么这里函数的返回值要求是void指针,但是返回的却是一个对象呢?那是因为我们的Php::Extension重载了cast-to-void-pointer-operator(转换到void指针类型的操作符),所以表面上你是返回了一个C++对象,但其实它只是返回了一个普通的C指针,这个指针指向的数据类型正是PHP内核能够理解的数据结构,并且这个数据结构包含了你扩展的所有细节。

最后我们直接在Ubuntu上测试一下我们的扩展(虽然它什么也没干)。

de  >cd EmptyExtenxion
make && sudo make installde>

成功后会显示编译好的文件以及位置:

de  >cp -f yourextension.so /usr/lib/php5/20121212
cp -f yourextension.ini /etc/php5/conf.dde>

在Ubuntu中,我是用de >apt-getde>安装的PHP,默认配置文件都再/etc/php5这个文件夹中,我们执行如下的操作:

de  >sudo ln -s /etc/php5/mods-available/yourextension.ini /etc/php5/cli/conf.d/10-yourextension.inide>

即可将我们编译好的扩展开启。(扩展路径保存在ini文件中,我们需要做的仅仅只是构建了一个文件链接到de >/etc/php5/cli/conf.dde>目录中)
用下列命令可以检测扩展是否正常加载

de  >php -i | grep yourextenxionde>

如果显示

de  >/etc/php5/cli/conf.d/10-yourextension.ini,
yourextensionde>

OK,就大功告成啦!






作者:Mindy
我是好人,好人就是我,我就是一码农Mindy
原文地址:使用PHP-CPP开发PHP扩展, 感谢原作者分享。

发表评论