前面已经了解了函数和参数,今天来了解一下类
例子
定义了一个 study_ext_class 类,里面只有一个 print 方法
类使用 PHP_ME和PHP_METHOD 宏,与方法最大的不同的地方是类需要注册
这里我写了一个 init_class 方法,PHP_MINIT_FUNCTION中调用,主要是需要注册类
PHP_MINIT_FUNCTION
这是我们扩展启动时会执行的一个函数,所以在这里注册类
PHP_METHOD
这两个宏和我们前面函数哪里的 PHP_FE ,PHP_FUNCTION 差不多
PHP_ME
PHP_ME 相比原来的 PHP_FE 多了几个参数,主要是方法的属性和类名
flags是方法的属性,我们可以用 | 连接它们
类注册
完成了上面的,编译&安装,实例化我们的类是是会报错的,因为php不知道你有那些类
方法的话,在最后面通过 ZEND_GET_MODULE 生成了一个 get_module 的接口将方法进行了返回
INIT_CLASS_ENTRY
这一个宏的作用是生成这个类的结构,包括类的名称,方法,然后返回在ce这个变量中
zend_register_internal_class
显而易见的是将我们的类的信息告诉php,注册进去,还有一个 zend_register_internal_class_ex 的函数,可以指定父类,然后这个函数返回我们的这个类的指针
构造和析构
函数列表哪里标记一下 ZEND_ACC_CTOR 或者 ZEND_ACC_DTOR 就好了
类属性
在初始化注册类的时候,使用 zend_declare_property_* 给我们的类添加属性,还可以给他们赋予默认值
输出
类指针和属性读取
上面写了怎么去定义属性,但是如果是在类里面要怎么使用属性呢?我们需要用一个 getThis 的宏来获取当前这个类的指针,我就偷懒直接在原来的 print 中添加了
zend_read_property
这个函数用于获取属性,还有zend_read_static_property,用法相同,不过这个是获取静态的属性,关于更新属性可以使用zend_update_property
第一个参数 scope 是这个类的指针,在之前的study_ce = zend_register_internal_class(&ce);获取,不过也可以这样获取Z_OBJCE_P(getThis())
第二个参数 object 是当前的对象,我们可以用getThis这个宏获取
第三个参数和第四个参数分别是 属性的名称和属性的长度
第五个参数 silent 用于是假设属性不存在的情况下是否报错
最后一个参数 rv 为魔术方法所返回的,如果不是魔术方法所返回的是一个NULL值,可以看我下面这个例子
getThis
获取对象指针,不多说了
类参数
其实和函数的参数一样,还有一个类似的zend_parse_method_parameters我用的时候总是错误,还没明白这个函数是干什么的,而且找不到说明的资料=_=,后面附上两个源码的区别再看看
探究
如果我们的第二个参数this_ptr为NULL或者不是OBJECT类型的话,那么效果和zend_parse_parameters一样,我之前填的是this指针,所以跳到了else分支
else分之第一句就是p++;表示字符串往后面移动一位,我填的参数是是一个单独的 l 然后一移动....没啦,后面还有两个va_arg
通过后面这两个得知,我们的两个参数,一个是 zval 的,一个是 zend_class_entry* 我们传入的 this_ptr 参数会赋值给 object 也就是我们后面的第四个参数,第五个是我们类的指针
看后面这一段,好像是校验类的,所以我觉得这个zend_parse_method_parameters和zend_parse_parameters的区别就在这里,method能够对类进行校验
使用
这里的type_spec我还加了一个O,因为在源码中,p++;这里跳过了一个字符,那么我们后面retval = zend_parse_va_args(num_args, p, &va, flags);的时候传入的就是 l 了, O 这里应该是可以乱填一个字符的
&this 又传回来了- -