zendAPI
项目不提供任何底层的功能,只是封装了 zend engine
提供的功能,对上提供一个易用的编程接口。这篇文章中,咱们将介绍 C++
世界与 C
世界交汇的地方,在这里也是 zendAPI
的接口与 zend engine
进行整合的地方,很是重要。 每个 PHP
扩展必须有一个描述对象,在 zendAPI
中咱们 zapi::lang::Extension
类主要的做用主要完成这个功能。如今咱们来看一个最简单的 zendAPI
项目的入口文件长什么样子:php
#include "zapi/ZendApi.h" extern "C" { ZAPI_DECL_EXPORT void *get_module() { static zapi::lang::Extension hellozapi("hellozapi", "1.0"); return hellozapi; } }
怎么样很简单吧,一个空的 PHP
扩展就完成了,如今咱们就详细解释下每行的做用。html
#include "zapi/ZendApi.h"
在开发基于 zendAPI
的项目时候,咱们只须要包含这个头文件就能够了,在这个头文件中,咱们会引入 zendAPI
平常开发须要的必要的头文件,您不用本身一个一个本身去引入。编程
extern "C" {}
在 CPP
代码与 C
代码进行链接的时候咱们通常会加上 extern wrapper
, 由于若是不加的话 CPP
编译器会对函数名称进行 name mangling
,这个会致使链接的时候提示符号不存在的错误。api
ZAPI_DECL_EXPORT void *get_module();
ZAPI_DECL_EXPORT
表示咱们扩展导出符号 get_module
给其余库使用。函数 get_module
这个函数很是重要,他是 zendAPI
与 zend engine
进行集成的入口,咱们必须在这个函数中设置好咱们扩展的一切,而后将扩展描述对象的指针返回。 在这里我先简单描述下 PHP
加载扩展这部分的过程: 在 PHP
初始化的过程当中调用的函数有:(这里咱们以 cli SAPI
为例进行说明)app
简单来讲咱们能够这样理解,在 PHP
模块初始化的时候,PHP
会去读取咱们在 php.ini
文件中注册的扩展, 好比我们的 hellozapi
就在 php.ini
注册了一行 extension=hellozapi.so
。若是相关的扩展文件存在,PHP
使用 dlopen
平台接口进行动态加载,成功的话, 获取 _get_module
符号,而后进行调用,最终获取一个 zend_module_entry
指针。函数
static zapi::lang::Extension hellozapi("hellozapi", "1.0");
这行代码实例化一个扩展对象,第一个参数是我们的扩展的名称,通常须要跟在 CMake
脚本中定义的项目名字保持一致,第二个参数指定扩展的版本号,这里咱们定义为 1.0
,这些信息咱们均可以在 PHP
脚本中经过反射技术获取同时也会出如今 phpinfo()
函数的输出中。 特别提醒:这里的 static
关键字不能去掉,去掉了咱们就返回了一个悬空指针。(dangle pointer)指针
return hellozapi;
新手可能会有疑问,咱们的 get_module
明明是返回一个 void *
,而咱们这里返回 zapi::lang::Extension
对象怎么也能够啊 ?原理很简单,由于咱们的 zapi::lang::Extension
定义了一个转换运算符,C++
编译器会自动进行类型转换。code
到这里,咱们这个空的 PHP
扩展就完成了,怎么样,简单吧?休息一下咱们继续。htm