IT技术博客大学习 共学习 共进步

PHP扩展内如何定义类、方法?

<?php $blog->author = "wudi"; 2016-03-30 15:57:09 累计浏览 2,204 次

PHP 类底层数据结构为 zend_class_entry 结构体,下面是摘录源代码 稍微了解下即可。
可以看到 有类名、继承父类入口,函数表,静态资源,属性(资产),各种魔术方法,继承接口,构造/析构函数等。

//详情 Zend/zend.h
struct_zend_class_entry{
chartype;
char*name;
zend_uint name_length;
struct_zend_class_entry *parent;
intrefcount;
zend_bool constants_updated;
zend_uint ce_flags;

HashTable function_table;
HashTable default_properties;
HashTable properties_info;
HashTable default_static_members;
HashTable *static_members;
HashTable constants_table;
conststruct_zend_function_entry *builtin_functions;

union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
union _zend_function *__get;
union _zend_function *__set;
union _zend_function *__unset;
union _zend_function *__isset;
union _zend_function *__call;
union _zend_function *__callstatic;
union _zend_function *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;

zend_class_iterator_funcs iterator_funcs;

/* handlers */
zend_object_value(*create_object)(zend_class_entry *class_type TSRMLS_DC);
zend_object_iterator *(*get_iterator)(zend_class_entry *ce,zval *object,intby_ref TSRMLS_DC);
int(*interface_gets_implemented)(zend_class_entry *iface,zend_class_entry *class_type TSRMLS_DC);/* a class implements this interface */
union _zend_function *(*get_static_method)(zend_class_entry *ce,char*method,intmethod_len TSRMLS_DC);

/* serializer callbacks */
int(*serialize)(zval *object,unsignedchar**buffer,zend_uint *buf_len,zend_serialize_data *data TSRMLS_DC);
int(*unserialize)(zval **object,zend_class_entry *ce,constunsignedchar*buf,zend_uint buf_len,zend_unserialize_data *data TSRMLS_DC);

zend_class_entry **interfaces;
zend_uint num_interfaces;

char*filename;
zend_uint line_start;
zend_uint line_end;
char*doc_comment;
zend_uint doc_comment_len;

struct_zend_module_entry *module;
};

typedefstruct_zend_class_entry zend_class_entry;

所以需要首先声明 类

//Tips: PHP源代码内 常见缩写为 xx_ce 即为某个类定义入口
zend_class_entry *demo_ce;  

那么类的定义写在哪里呢?

这要看你所需要的初始化阶段,一般在 PHP_MINIT_FUNCTION 阶段或 ZEND_MINIT_FUNCTION 内,即 当扩展模块加载时(PHP 启动时/代码内手动load时)处理。
当然看业务需求 也可以在 每个Request请求时处理 PHP_RINIT_FUNCTION 内。
这里有个小技巧,如果可能尽量把类入口定义 抽出到公共区域,因为你在定义各种属性方法,使用函数时,都会需要类 ce 入口作为参数,这里我们建议写在文件尽量考前的位置(比如 include 之后)。

定义完 zend_class_entry 就完了?

当然不可能,你可能想到了 我 TM 类名还没设置呢就完了。。。。

//类内部方法声明、具体实现
PHP_METHOD(demo,foo){
   php_printf("call method foo in class demo.\n");
}

//这一步是对应绑定到具体类 对应方法 类似 bind 动作
staticzend_function_entry demo_methods[]={
        //参数: 类名,方法名,方法参数信息,方法访问权限,例如 public, privite, protected 
ZEND_ME(demo,    foo,  NULL,   ZEND_ACC_PUBLIC)
NULL,NULL,NULL
};

PHP_MINIT_FUNCTION(demo)  //MINIT阶段
{
   //再次定义一个类入口
   zend_class_entry ce;
 
   //初始化类 
   INIT_CLASS_ENTRY(ce,"demo",methods);  
 
   //把类注册到zend 内部, 并且把返回值 zend_class_entry 类型赋值给 上面注册的公共类变量
   demo_ce=zend_register_internal_class(&amp;ce TSRMLS_CC);
}

//Tips: 已上初始类的三句话,经常用到,可以自定义宏替换,避免过于麻烦。(本次不使用)
例如:
#define DEMO_INIT_CLASS(class_ce, class_name, functions) \
zend_class_entry ce;\
INIT_CLASS_ENTRY(ce,class_name,functions);\
class_ce=zend_register_internal_class(&amp;ce TSRMLS_CC);

接着重新编译ini引入扩展 就可以尝试 使用对象了

$obj=newdemo;

$obj-&gt;foo();

//call method foo in class demo.

当然对类操作还有很多其他高级功能,比如说: 定义/初始化类属性,定义类常量,类方法互相调用,静态方法,类继承类/接口,类命名空间等等,后续一一讲解记录。

建议继续学习

  1. chrome扩展应用开发教程之开发chrome应用基础 (累计阅读 5,605)
  2. PHP内核介绍及扩展开发指南―高级主题 (累计阅读 4,586)
  3. chrome扩展应用开发教程之调试和打包上线 (累计阅读 4,426)
  4. 深入理解PHP原理之扩展载入过程 (累计阅读 4,385)
  5. Mediawiki扩展编写实战 (累计阅读 4,384)
  6. 编写python的C语言扩展 (累计阅读 4,325)
  7. PHP内核介绍及扩展开发指南―类和对象 (累计阅读 4,006)
  8. 用C/C++扩展你的PHP (累计阅读 3,766)
  9. PHP7扩展开发之hello word (累计阅读 3,568)
  10. PHP扩展开发:第一个扩展 (累计阅读 3,545)