在zval变量里IS_OBJECT类型使用zend_object_value来保存变量的,我们看一下他的具体结果。

typedef struct _zend_object_value {
zend_object_handle handle;
const zend_object_handlers *handlers;
} zend_object_value;

在扩展中创建一个我们自己的类

zend_class_entry *myext_class_ce;//保存我们创建的对象实例

static zend_function_entry myext_class_method[] = {//函数的属性和方法都在这里定义
{NULL, NULL, NULL}//固定语法
}; //在MINIT函数里
PHP_MINIT_FUNCTION(myext)
{
zend_class_entry tmp_myext_class_ce;//临时变量
INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);//临时变量,类名称,类属性和方法
myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//在内核中注册我们的类
} /* $class = new myext_example_class();

var_dump($class);

object(myext_example_class)#6 (0) {
  }

*/

创建类的第一个函数

ZEND_METHOD(myext_example_class,hello);

//ZEND_ME为方法注册,每个方法使用一个ZEND_ME
//参数说明
//1,类名称
//2,方法名称
//3,参数,跟普通函数的一样,也是ZEND_END_ARG_INFO
//4,修饰方法或属性,后面会专门讲到
static zend_function_entry myext_class_method[] = {
ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}//固定语法
}; //函数定义,参数说明:
//类名称
//类方法名称
ZEND_METHOD(myext_example_class,hello){
php_printf("hello");
}

创建一个构造函数__construct()

ZEND_METHOD(myext_example_class,__construct);

//创建构造方法同普通方法基本一样,唯一的差别在于第四个参数,ZEND_ACC_CTOR,表示它是构造方法
static zend_function_entry myext_class_method[] = {
ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
{NULL, NULL, NULL}//固定语法
}; ZEND_METHOD(myext_example_class,__construct){
php_printf("我是__construct函数");
}

现在来看一下修饰方法和属性的常量,通过他们可以定义方法的访问权限,是否是抽奖函数,是否是FINAL属性等等

下面详细的罗列出了所有常量,fn_flags代表可以在定义方法时使用,zend_property_info.flags代表可以在定义属性时使用,ce_flags代表在定义zend_class_entry时候可用。当需要用到多个常量的时候,我们可以采用或运算的形式,在定义构造函数的时候,我们已经遇到了,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR

#define ZEND_ACC_STATIC                     0x01     /* fn_flags, zend_property_info.flags 静态方法或属性*/
#define ZEND_ACC_ABSTRACT 0x02 /* fn_flags 抽象*/
#define ZEND_ACC_FINAL 0x04 /* fn_flags 最终方法*/
#define ZEND_ACC_IMPLEMENTED_ABSTRACT 0x08 /* fn_flags 接口抽象方法*/
#define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS 0x10 /* ce_flags */
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20 /* ce_flags */
#define ZEND_ACC_FINAL_CLASS 0x40 /* ce_flags */
#define ZEND_ACC_INTERFACE 0x80 /* ce_flags */
#define ZEND_ACC_INTERACTIVE 0x10 /* fn_flags */
#define ZEND_ACC_PUBLIC 0x100 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PROTECTED 0x200 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PRIVATE 0x400 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)
#define ZEND_ACC_CHANGED 0x800 /* fn_flags, zend_property_info.flags */
#define ZEND_ACC_IMPLICIT_PUBLIC 0x1000 /* zend_property_info.flags; unused (1) */
#define ZEND_ACC_CTOR 0x2000 /* fn_flags */
#define ZEND_ACC_DTOR 0x4000 /* fn_flags */
#define ZEND_ACC_CLONE 0x8000 /* fn_flags */
#define ZEND_ACC_ALLOW_STATIC 0x10000 /* fn_flags */
#define ZEND_ACC_SHADOW 0x20000 /* fn_flags */
#define ZEND_ACC_DEPRECATED 0x40000 /* fn_flags */
#define ZEND_ACC_CLOSURE 0x100000 /* fn_flags */
#define ZEND_ACC_CALL_VIA_HANDLER 0x200000 /* fn_flags */

现在我们为这个类增加一些属性。添加属性变量需要在MINIT函数中实现,在类创建完成之后,我们就可以添加属性了

    zend_class_entry tmp_myext_class_ce;
INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
//上面是创建类,下面是添加属性
//创建普通属性和静态属性的方法是一样,只需要在第四个参数中增加ZEND_ACC_STATIC即为静态属性
//创建类常量是另外一组的函数,和普通属性不一样
zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-,ZEND_ACC_PRIVATE TSRMLS_CC);//私有权限,默认值为NULL
zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);//protected权限,默认值是"我是默认值"
zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-,,ZEND_ACC_PUBLIC TSRMLS_CC);//public,默认值是100
zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);//静态变量,默认值是"我是静态变量"
zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - ,"我是类常量" TSRMLS_CC);//类常量,默认值是"我是类常量"
/*

$class = new myext_example_class();
var_dump($class);
$class->hello();
var_dump(myext_example_class::$static_prop);
var_dump(myext_example_class::CONSTANT_PROP);

object(myext_example_class)#6 (3) {
["private_prop":"myext_example_class":private]=>
NULL
["protected_prop":protected]=>
string(15) "我是默认值"
["public_prop"]=>
int(100)
}
hello

string(18) "我是静态变量"
string(15) "我是类常量"

*/

在php内核中,由于操作变量的类型不同,通常同样一个功能,会有一组函数,上面我们提到的创建类属性和类常量也是有一组操作。

//以下操作都是在zend_API.h
//定义类属性
ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC);
ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC); //定义类常量
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC);
ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC);
ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC);

接下来,我们来看一下,接口的实现,以及接口和类的继承

定义一个接口,这个过程与定义类类似

zend_class_entry *myext_interface_ce;

static zend_function_entry myext_interface_method[] = {
ZEND_ABSTRACT_ME(myext_interface_ce,int_func,NULL)//定义一个抽奖方法,这个方法可以不实现,也就是不需要存在一个ZEND_ME(myext_interface_ce,int_func)
{NULL, NULL, NULL}//固定语法
}; zend_class_entry tmp_myext_interface_ce;
INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC);//注册接口的函数与注册类的不一样 /*

class interface_class implements myext_example_interface{
public function int_func(){
echo "我继承了接口\n";
}
}

$interface_class = new interface_class();
$interface_class->int_func();

我继承了接口

*/

我们在扩展的代码里实现继承,让myext_example_class继承myext_example_interface

ZEND_METHOD(myext_example_class,int_func);//php_myext.h

//抽象函数int_func的实现
ZEND_METHOD(myext_example_class,int_func){
php_printf("我是class继承了接口interface");
} static zend_function_entry myext_class_method[] = {
ZEND_ME(myext_example_class,hello,NULL,ZEND_ACC_PUBLIC)
ZEND_ME(myext_example_class,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
ZEND_ME(myext_example_class,int_func,NULL,ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}//固定语法
}; zend_class_entry tmp_myext_interface_ce;
INIT_CLASS_ENTRY(tmp_myext_interface_ce,"myext_example_interface",myext_interface_method);
myext_interface_ce = zend_register_internal_interface(&tmp_myext_interface_ce TSRMLS_CC); zend_class_entry tmp_myext_class_ce;
INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);
zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-,ZEND_ACC_PRIVATE TSRMLS_CC);
zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-,,ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - ,"我是类常量" TSRMLS_CC);
zend_class_implements(myext_class_ce TSRMLS_CC,,myext_interface_ce);//这句话表示myext_class_ce继承接口myext_interface_ce /*

$class = new myext_example_class();

$class->int_func();

我是class继承了接口interface

*/

我们再来实现一个类继承的例子

ZEND_METHOD(myext_example_class,class_func);//php_myext.h
ZEND_METHOD(myext_example_parent_class,class_func);//php_myext.h zend_class_entry *myext_parent_class_ce;//保存父类的变量 static zend_function_entry myext_parent_class_method[] = {
ZEND_ME(myext_example_parent_class,class_func,NULL,ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}//固定语法
}; zend_class_entry tmp_myext_parent_class_ce;
INIT_CLASS_ENTRY(tmp_myext_parent_class_ce,"myext_example_parent_class",myext_parent_class_method);
myext_parent_class_ce = zend_register_internal_class(&tmp_myext_parent_class_ce TSRMLS_CC);//注册一个myext_example_parent_class zend_class_entry tmp_myext_class_ce;
INIT_CLASS_ENTRY(tmp_myext_class_ce,"myext_example_class",myext_class_method);
//myext_class_ce = zend_register_internal_class(&tmp_myext_class_ce TSRMLS_CC);//正常注册类
myext_class_ce = zend_register_internal_class_ex(&tmp_myext_class_ce,myext_parent_class_ce,"myext_example_parent_class" TSRMLS_CC);//继承注册类,第一个参数是一样的,第二个是继承父类的变量,第三个是父类的名称
zend_declare_property_null(myext_class_ce,"private_prop",sizeof("private_prop")-,ZEND_ACC_PRIVATE TSRMLS_CC);
zend_declare_property_string(myext_class_ce,"protected_prop",sizeof("protected_prop")-,"我是默认值",ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_long(myext_class_ce,"public_prop",sizeof("public_prop")-,,ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_string(myext_class_ce,"static_prop",sizeof("static_prop")-,"我是静态变量",ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);
zend_declare_class_constant_string(myext_class_ce,"CONSTANT_PROP",sizeof("CONSTANT_PROP") - ,"我是类常量" TSRMLS_CC);
zend_class_implements(myext_class_ce TSRMLS_CC,,myext_interface_ce); ZEND_METHOD(myext_example_parent_class,class_func){
php_printf("我是父类的class_func\n");
} ZEND_METHOD(myext_example_class,class_func){
php_printf("我是子类的class_func\n");
} /*

$parent_class = new myext_example_parent_class();
$parent_class->class_func();
$class = new myext_example_class();
$class->class_func();

我是父类的class_func
我是__construct函数
我是子类的class_func

*/              

接着我们来看一下怎么样在类方法中使用类的属性变量

ZEND_METHOD(myext_example_class,read_property){
zval *private_prop,*protected_prop,$public_prop;
zval *static_prop;
zend_class_entry *ce; ce = Z_OBJCE_P(getThis()); private_prop = zend_read_property(myext_class_ce,getThis(),"private_prop",sizeof("private_prop") - , TSRMLS_CC);//获取private_prop的属性值,相当于php的$this->private_prop
php_var_dump(&private_prop, TSRMLS_CC);
protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - , TSRMLS_CC);
php_var_dump(&protected_prop, TSRMLS_CC); static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - , TSRMLS_CC);//获取静态属性static_prop的属性值,相当于php的self::$static_prop
php_var_dump(&static_prop, TSRMLS_CC); zend_update_property_string(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - ,"更新protected_prop的值" TSRMLS_CC);//设置protected_prop的属性值,相当于php的$this->protected_prop = "更新protected_prop";
protected_prop = zend_read_property(myext_class_ce,getThis(),"protected_prop",sizeof("protected_prop") - , TSRMLS_CC);
php_var_dump(&protected_prop, TSRMLS_CC); zend_update_static_property_string(myext_class_ce,"static_prop",sizeof("static_prop") - ,"更新static_prop的值" TSRMLS_CC);//设置静态属性static_prop的属性值,相当于php的self::$static_prop = "更新static_prop的值";
static_prop = zend_read_static_property(ce,"static_prop",sizeof("static_prop") - , TSRMLS_CC); 

php_var_dump(&static_prop, TSRMLS_CC); }
//zend_update_property*的一组函数
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC); //
zend_update_static_property*的一组函数
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC); 
ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);

php扩展开发-面向对象的更多相关文章

  1. iOS开发系列--App扩展开发

    概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...

  2. PHP 扩展开发(将自己的一些代码封装成PHP扩展函数)

    今天时间不多,先给个地址,能搜到我这篇blog的朋友先看看我最近在看的一些文章.资料吧: 我的环境是 lnmp1.1 的 (LNMP一键安装包),所以要进行PHP扩展开发首先应该对环境配置和shell ...

  3. 关于PHP扩展开发(收藏)

    一.Linux shell命令: ls –lh    查看文件大小 du –a    查看文件及文件夹大小 -------------------------- nginx ------------- ...

  4. postgres扩展开发

    扩展开发的基本组成 demo--1.0.sql demo.c demo.control Makefile demo.c当中包含了自定义函数的实现,纯C语言,目录下可包含多个.c文件.demo-1.0. ...

  5. 【转发】NPAPI学习(Firefox和Chrome扩展开发 )

    NPAPI学习(Firefox和Chrome扩展开发 ) 2011-11-08 14:41:02 by [6yang], 1172 visits, 收藏 | 返回 Firefox和Chrome扩展开发 ...

  6. Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  7. PHP扩展开发相关总结

    1.线程安全宏定义 在TSRM/TSRM.h文件中有如下定义 #define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, ...

  8. Firefox扩展开发

    Firefox扩展开发 (插件开发) Extension开发 入门教程 5步走 五步走   首先需要知道什么是"Firefox插件".这里说的"插件"只是一个通 ...

  9. Chrome浏览器扩展开发系列之十四

    Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 时间:2015-10-08 16:17:59      阅读:1361      评论:0      收藏:0    ...

随机推荐

  1. [Java][Liferay] 如何从Javascript的function中获取language property的值

    问题描述 在Portlet中,Javascript中通过Liferay.Language.get("key")的方式是拿不到自己添加的property的值,原因是Liferay.L ...

  2. 粗看ES6之数组

    标签: javascript es6 数组新增方法 map(可以理解为是映射,以一定规则修改数组每一项并返回全新数组) reduce(可以理解为是汇总,一堆出来一个) filter(可以理解为过滤,筛 ...

  3. cf868F. Yet Another Minimization Problem(决策单调性 分治dp)

    题意 题目链接 给定一个长度为\(n\)的序列.你需要将它分为\(m\)段,每一段的代价为这一段内相同的数的对数,最小化代价总和. \(n<=10^5,m<=20\) Sol 看完题解之后 ...

  4. [原创]Centos7 安装配置ASP.NET Core+Nginx+Supervisor

    序言 此教程安装的都是最新版本的. 一键安装 有了这个神器,下面的教程就不用做了!只需运行几行代码,直接打开浏览器就可以访问! cd /home/ wget https://files.cnblogs ...

  5. SQL Server2005修改计算机名后不能发布订阅

    在一台安装有SQL Server2005的计算机上,更改计算机名后,在发布订阅的时候提示如下错误报告: 由于需要需要配置一个发布订阅,可是一直报告:" sql server 复制需要有实际的 ...

  6. Struts2 简介及学习方法介绍

    Struts2 =  webwork + struts1.x 尊重学习规律的操作 学习上痛苦的根源之一是只能走的时候逼我来跑 不是说深入的内容就不讲了,而是放到合适的时候讲 一段时间可以,长了集中不了 ...

  7. vos优化客户线路数量

    问题: 客户A打电话过来说之前给开的300线路不够用了,今天好多电话呼不出去了,线路太挤了! 麻烦增加线路,如何操作? 方法: 登陆VOS——在线对接——(客户A的对接网关ID)——双击 打开网关管理 ...

  8. shell脚本学习(3)文件判断

    shell常用的文件判断运算符如下: -e 文件是否存在 -f  文件是否是普通文件(不是目录.设备文件.链接文件) -s  表示文件大小不为0 -d 表示文件是否是目录 -b 表示是块设备(光驱.软 ...

  9. Tensorflow ValueError: Protocol message RewriterConfig has no "layout_optimizer" field

    I changed models/research/object_detection/exporter.py line 71/72 from: rewrite_options = rewriter_c ...

  10. 虚拟机的NAT模式连接centos7配置静态IP连接外网

    小小的配置,各种五花八门的介绍. 1.打开VMWare->编辑->虚拟网络编辑器->点击更改设置 2.选中VMnet8->取消使用本地DHCP服务将IP地址分配给虚拟机-> ...