zendAPI项目不提供任何底层功能,只是对zend引擎提供的功能进行封装,提供简单易用的编程接口。在这篇文章中,我们将介绍C++世界与C世界相遇的地方,也是zendAPI接口与zendengine集成的地方,这是非常重要的。每个PHP扩展都必须有一个描述对象。在zendAPI中,我们的zapi::lang::Extension类的主要作用就是完成这个功能。现在让我们看看最简单的zendAPI项目的入口文件是什么样子的:“1.0”);returnhellozapi;}}怎么样就很简单了,一个空的PHP扩展就完成了,下面详细解释一下每一行的作用。#include"zapi/ZendApi.h"在开发基于zendAPI的项目时,我们只需要包含这个头文件。在这个头文件中,我们将介绍zendAPI日常开发所需要的必要头文件。你不需要自己一一介绍。extern"C"{}我们通常在连接CPP代码和C代码时添加externwrapper,因为如果不添加,CPP编译器会对函数名进行namemangling,会导致连接存在错误时提示符号不正确。ZAPI_DECL_EXPORTvoid*get_module();ZAPI_DECL_EXPORT表示我们扩展导出符号get_module以供其他库使用。get_module函数非常重要。它是zendAPI和zend引擎集成的入口点。我们必须在这个函数中设置我们扩展的所有内容,然后返回扩展描述对象的指针。这里简单描述一下PHP加载扩展的过程:PHP初始化时调用的函数有:(这里以cliSAPI为例进行说明)");调用get_module获取zend_module_entry对象指针。简单的说,我们可以理解为PHP模块初始化时,PHP会读取我们在php.ini文件中注册的扩展。比如我们的hellozapi是在php.ini中注册了一行extension=hellozapi.so。如果相关扩展文件存在,PHP使用dlopen平台接口进行动态加载,如果成功,获取_get_module符号,然后调用它,最后获取一个zend_module_entry指针。静态zapi::lang::Extensionhellozapi("hellozapi","1.0");这行代码实例化了一个扩展对象,第一个参数是我们扩展的名称,后面一般需要跟CMake脚本中定义的项目名称保持一致,第二个参数指定扩展的版本号,这里我们定义为1.0,我们可以在PHP脚本中通过反射技术获取这些信息,它也会出现在phpinfo()函数的输出中。特别提醒:这里的static关键字不能去掉。如果它被移除,我们将返回一个悬挂指针。(悬挂指针)返回hellozapi;新手可能会有疑惑,我们的get_module明明返回的是一个void*,但是怎么会在这里返回一个zapi::lang::Extension对象呢?原理很简单,因为我们的zapi::lang::Extension定义了一个转换运算符,C++编译器会自动进行类型转换。至此,我们的空PHP扩展就完成了,怎么样,简单吗?休息一下,我们继续。文中使用的编程文档参考链接ZAPI_DECL_EXPORT参考手册zapi::lang::ExtensionReferenceManual原文链接:C++开发PHP7扩展模块入口定义
