自己写PHP扩展之创建一个类
Jun 06, 2016 pm 07:57 PM
php
创建
博客
声明
扩展
自己
声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。 http://imsiren.com/archives/572 上一章用扩展创建了一个变量.. 这次来个大的..我们创建一个类. 然后在php里面去调用这个类. 生成扩展及修改 不知道的请点击这里 http://imsiren.com/a
声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。
http://imsiren.com/archives/572
上一章用扩展创建了一个变量..
这次来个大的..我们创建一个类.然后在php里面去调用这个类.
生成扩展及修改 不知道的请点击这里 http://imsiren.com/archives/568
这里就不谈了.
比如我们要创建一个类..PHP代码如下
class Person { public $name; public $age; public function __construct() { echo "construct is running! "; } public function __destruct() { echo " destruct is running!"; } public function getproperty($key) { echo $this->$key; } public function setproperty($key,$val) { $this->$key = $val; } }
登录后复制
那么用PHP扩展来写该怎么做?
OK.
1.在php_siren.h里面声明类
PHP_METHOD(Person,__construct); PHP_METHOD(Person,__destruct); PHP_METHOD(Person,setproperty); PHP_METHOD(Person,getproperty);
登录后复制
PHP_METHOD宏.
PHP_METHOD 等于ZEND_METHOD
这个宏接受两个参数,第一个是类名,第二个是类的方法
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name)) #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v alue_used TSRMLS_DC //最后等于 void name(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v alue_used TSRMLS_DC )
登录后复制
这个宏是用来声明我们的方法...
2.设置接收的参数
我们的方法如果需要接受参数.那么就要执行
ZEND_BEGIN_ARG_INFO_EX(arg_person_info,0,0,2) ZEND_ARG_INFO(0,name) ZEND_END_ARG_INFO()
登录后复制
详细讲这几个宏之前先看看zend_arg_info
typedef struct _zend_arg_info { const char *name; //参数名称 zend_uint name_len;//长度 const char *class_name; //所属类名 zend_uint class_name_len; //类名长度 zend_bool array_type_hint; zend_bool allow_null; //允许为空 zend_bool pass_by_reference; //引用传值 zend_bool return_reference; //引用返回 int required_num_args; //参数个数 } zend_arg_info;
登录后复制
ZEND_BEGIN_ARG_INFO_EX定义在Zend/zend_API.h
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ static const zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
登录后复制
很明显 声明一个zend_arg_info的数组name,然后初始化结构体的值
ZEND_ARG_INFO(0,name)的定义如下
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
登录后复制
这三个宏 执行代码 等于
static const zend_arg_info name[] = { { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, };
登录后复制
3.创建zend_function_entry结构数组
const zend_function_entry person_functions[]={ PHP_ME(Person,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Person,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_ME(Person,getproperty,arg_person_info,ZEND_ACC_PUBLIC) PHP_ME(Person,setproperty,arg_person_info,ZEND_ACC_PUBLIC) PHP_FE_END };
登录后复制
登录后复制
typedef struct _zend_function_entry { const char *fname; //函数名称 void (*handler)(INTERNAL_FUNCTION_PARAMETERS); const struct _zend_arg_info *arg_info;//参数 zend_uint num_args;//参数个数 zend_uint flags;//标示PUBLIC ?PRIVATE ?PROTECTED } zend_function_entry;
登录后复制
PHP_ME宏接收四个参数
1 类名,
2 方法名,
3 zend_arg_info 的参数列表,
ZEND_ACC_PUBLIC ZEND_ACC_PRIVATE ZEND_ACC_PROTECTED是我们类里面的三个访问权限
ZEND_ACC_CTOR标示构造函数
ZEND_ACC_DTOR标示析构函数
4.修改PHP_MINIT_FUNCTION
前面我们说过 PHP_MINIT_FUNCTION是在模块启动的时候执行的函数
首先创建一个全局指针 zend_class_entry *person_ce;
在PHP_MINIT_FUNCTION加入如下代码
zend_class_entry person; INIT_CLASS_ENTRY(person,"Person",person_functions); person_ce=zend_register_internal_class_ex(&person,NULL,NULL TSRMLS_CC); zend_declare_property_null(person_ce,ZEND_STRL("name"),ZEND_ACC_PUBLIC TSRMLS_CC);
登录后复制
1行创建一个zend_class_entry对象person.
zend_class_entry这个结构体前面也讲过 PHP内核研究之类的实现
2行初始化zend_class_entry 它执行了如下代码
{ \ int _len = class_name_len; \ class_container.name = zend_strndup(class_name, _len); \ class_container.name_length = _len; \ class_container.builtin_functions = functions; \ class_container.constructor = NULL; \ class_container.destructor = NULL; \ class_container.clone = NULL; \ class_container.serialize = NULL; \ class_container.unserialize = NULL; \ class_container.create_object = NULL; \ class_container.interface_gets_implemented = NULL; \ class_container.get_static_method = NULL; \ class_container.__call = handle_fcall; \ class_container.__callstatic = NULL; \ class_container.__tostring = NULL; \ class_container.__get = handle_propget; \ class_container.__set = handle_propset; \ class_container.__unset = handle_propunset; \ class_container.__isset = handle_propisset; \ class_container.serialize_func = NULL; \ class_container.unserialize_func = NULL; \ class_container.serialize = NULL; \ class_container.unserialize = NULL; \ class_container.parent = NULL; \ class_container.num_interfaces = 0; \ class_container.interfaces = NULL; \ class_container.get_iterator = NULL; \ class_container.iterator_funcs.funcs = NULL; \ class_container.module = NULL; \ }
登录后复制
可以对应 PHP内核研究之类的实现 来分析
5.创建 php_siren.h头文件中的方法体
PHP_METHOD(Person,__construct){ php_printf("construct is running<br>"); } PHP_METHOD(Person,__destruct){ php_printf("destruct is running<br>"); } PHP_METHOD(Person,setproperty){ } PHP_METHOD(Person,getproperty){ }
登录后复制
6.最后make&& make install
编译我们的扩展,
重新启动apache.
$p=new Person();
?>
我们就能在浏览器里看到输出的内容
construct is running
destruct is running
这样 ..我们用扩展创建的一个基本类就完成了.
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门文章
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 周前
By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
3 周前
By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前
By 尊渡假赌尊渡假赌尊渡假赌
击败分裂小说需要多长时间?
3 周前
By DDD
公众号网页更新缓存难题:如何避免版本更新后旧缓存影响用户体验?
3 周前
By 王林

热门文章
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 周前
By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
3 周前
By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前
By 尊渡假赌尊渡假赌尊渡假赌
击败分裂小说需要多长时间?
3 周前
By DDD
公众号网页更新缓存难题:如何避免版本更新后旧缓存影响用户体验?
3 周前
By 王林

热门文章标签

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发
