IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

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

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

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. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,270)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,408)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,149)
  5. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,790)
  6. 15个最好的免费开源电子商务平台 (累计阅读 12,541)
  7. Redis消息队列的若干实现方式 (累计阅读 12,088)
  8. 到底什么是MVC? (累计阅读 11,869)
  9. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,709)
  10. Rolling cURL: PHP并发最佳实践 (累计阅读 11,488)