摘要:每一个扩展必须有一个描述对象,在中我们类主要的作用主要完成这个功能。表示我们扩展导出符号给其他库使用。文章使用的编程文档的引用连接参考手册参考手册原文链接开发扩展之模块入口定义
zendAPI 项目不提供任何底层的功能,只是封装了 zend engine 提供的功能,对上提供一个易用的编程接口。这篇文章中,我们将介绍 C++ 世界与 C 世界交汇的地方,在这里也是 zendAPI 的接口与 zend engine 进行整合的地方,非常重要。
每一个 PHP 扩展必须有一个描述对象,在 zendAPI 中我们 zapi::lang::Extension 类主要的作用主要完成这个功能。现在我们来看一个最简单的 zendAPI 项目的入口文件长什么样子:
#include "zapi/ZendApi.h" extern "C" { ZAPI_DECL_EXPORT void *get_module() { static zapi::lang::Extension hellozapi("hellozapi", "1.0"); return hellozapi; } }
怎么样很简单吧,一个空的 PHP 扩展就完成了,现在我们就详细解释下每行的作用。
#include "zapi/ZendApi.h"
在开发基于 zendAPI 的项目时候,我们只需要包含这个头文件就可以了,在这个头文件中,我们会引入 zendAPI 日常开发需要的必要的头文件,您不用自己一个一个自己去引入。
extern "C" {}
在 CPP 代码与 C 代码进行连接的时候我们一般会加上 extern wrapper, 因为如果不加的话 CPP 编译器会对函数名称进行 name mangling,这个会导致连接的时候提示符号不存在的错误。
ZAPI_DECL_EXPORT void *get_module();
ZAPI_DECL_EXPORT 表示我们扩展导出符号 get_module 给其他库使用。函数 get_module 这个函数非常重要,他是 zendAPI 与 zend engine 进行集成的入口,我们必须在这个函数中设置好我们扩展的一切,然后将扩展描述对象的指针返回。
在这里我先简单描述下 PHP 加载扩展这部分的过程:
在 PHP 初始化的过程中调用的函数有:(这里我们以 cli SAPI 为例进行说明)
php_cli_startup
php_module_startup
php_ini_register_extensions
php_load_extension
get_module = (zend_module_entry ()(void)) DL_FETCH_SYMBOL(handle, "_get_module");
调用 get_module,获取zend_module_entry 对象指针
简单来说我们可以这样理解,在 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++ 编译器会自动进行类型转换。
到这里,我们这个空的 PHP 扩展就完成了,怎么样,简单吧?休息一下我们继续。
文章使用的编程文档的引用连接ZAPI_DECL_EXPORT 参考手册
zapi::lang::Extension 参考手册
原文链接: C++ 开发 PHP 7 扩展之模块入口定义
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/25938.html
摘要:比如扩展的那么我们必须也在我们扩展中也定义几个常量玩玩啊,其实真的很简单,不信那咱们走着看。好了,到这里我们就把预定义常量就讲完了,我没有骗您吧,真的很简单,稍作调整让我们继续前进原文链接开发扩展之定义常量 大家如果经常阅读 PHP 官方手册的话会发现,在扩展那一章里面的每个扩展的介绍的时候,都有一节是 Predefined Constants 预定义常量,这些常量是不需要您在 PHP...
摘要:大家如果经常阅读官方手册的话会发现,在扩展那一章里面的每个扩展的介绍的时候,都有一节是预定义常量,这些常量是不需要您在里面进行定义就可以使用的。比如扩展的那么我们必须也在我们扩展中也定义几个常量玩玩啊,其实真的很简单,不信那咱们走着看。 大家如果经常阅读 PHP 官方手册的话会发现,在扩展那一章里面的每个扩展的介绍的时候,都有一节是 Predefined Constants 预定义常量...
摘要:主要是库文件头文件文件不一致的问题。定义模块函数其中函数参数是模块自身,是传递的参数列表,返回值定义了一个整形数,这里会申请空间增加引用计数,交由来管理这个引用。 C++开发python windows版本的扩展模块示例测试环境介绍和准备测试环境:操作系统:windows10Python版本:3.7.0VS版本:vs2015社区版(免费)相关工具下载:VS版本vs2015社区版(免费)...
摘要:主要是库文件头文件文件不一致的问题。定义模块函数其中函数参数是模块自身,是传递的参数列表,返回值定义了一个整形数,这里会申请空间增加引用计数,交由来管理这个引用。 C++开发python windows版本的扩展模块示例测试环境介绍和准备测试环境:操作系统:windows10Python版本:3.7.0VS版本:vs2015社区版(免费)相关工具下载:VS版本vs2015社区版(免费)...
摘要:第一步打开项目下的文件,在文件中输入我们的函数的原型声明代码。这行代码注册一个原型为的函数,当这个函数被执行的时候,我们的函数将被运行时调用。原文地址开发扩展之原生函数定义 在上一篇中我们在hellozapi扩展中我们定义了几个常量,但是一个有用的扩展,必须得有函数,没有函数的扩展啥用没有,如果您觉得定义函数很难的话,您又错了,zendAPI就是为了让您生活变得美好而生的,而不会让事情...
阅读 3378·2021-10-14 09:42
阅读 2672·2021-09-08 10:44
阅读 1266·2021-09-02 10:18
阅读 3545·2021-08-30 09:43
阅读 2756·2021-07-29 13:49
阅读 3663·2019-08-29 17:02
阅读 1543·2019-08-29 15:09
阅读 977·2019-08-29 11:01