在PHP扩展中定义一个类,是非常容易的,见地址:
https://github.com/walu/phpbook/blob/master/10.1.md
类的结构体定义:
struct _zend_class_entry {
char type;
char *name;
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
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;
const struct _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, int by_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, int method_len TSRMLS_DC);
/* serializer callbacks */
int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *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;
char type;
char *name;
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
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;
const struct _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, int by_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, int method_len TSRMLS_DC);
/* serializer callbacks */
int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *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;
};
定义一个类,关键就这么几行:
zend_class_entry *myclass_ce;
static zend_function_entry myclass_method[] = {
{ NULL, NULL, NULL }
};
ZEND_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
//"myclass"是这个类的名称。
INIT_CLASS_ENTRY(ce, "myclass",myclass_method);
myclass_ce = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
static zend_function_entry myclass_method[] = {
{ NULL, NULL, NULL }
};
ZEND_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
//"myclass"是这个类的名称。
INIT_CLASS_ENTRY(ce, "myclass",myclass_method);
myclass_ce = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
层层展开宏INIT_CLASS_ENTRY :
#define INIT_CLASS_ENTRY(class_container, class_name, functions) \
INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \
INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL)
#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
{ \
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; \
}
#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \
INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-1, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL)
#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
{ \
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; \
}
通过展开宏,我发现,在执行完INIT_CLASS_ENTRY后,其实zend_class_entry结构,只初始化了三个成员,name,name_length,builtin_functions
其中builtin_functions指向自己定义的类的方法数组。
注册类的最后一步:
ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
{
return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
}
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
{
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
char *lowercase_name = malloc(orig_class_entry->name_length + 1);
*class_entry = *orig_class_entry;
class_entry->type = ZEND_INTERNAL_CLASS;
zend_initialize_class_data(class_entry, 0 TSRMLS_CC); /* 这一步,主要是完成zend_class_entry结构的各种HashTable成员的初始化,如default_properties,properties_info等 */
class_entry->ce_flags = ce_flags;
class_entry->module = EG(current_module);
if (class_entry->builtin_functions) {
zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); /* 这一步,完成zend_class_entry结构中各种函数指针的赋值,如果我们在builtin_functions中实现了这个方法的话,比如各种__call,__get,__set以及constructor,destructor方法等。 */
}
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); /* 最后,将类添加到runtime 的全局class_table这个HashTable中,这里将类名转成lowercase的了,所以类名不区分大小写 */
free(lowercase_name);
return class_entry;
{
return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
}
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
{
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
char *lowercase_name = malloc(orig_class_entry->name_length + 1);
*class_entry = *orig_class_entry;
class_entry->type = ZEND_INTERNAL_CLASS;
zend_initialize_class_data(class_entry, 0 TSRMLS_CC); /* 这一步,主要是完成zend_class_entry结构的各种HashTable成员的初始化,如default_properties,properties_info等 */
class_entry->ce_flags = ce_flags;
class_entry->module = EG(current_module);
if (class_entry->builtin_functions) {
zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); /* 这一步,完成zend_class_entry结构中各种函数指针的赋值,如果我们在builtin_functions中实现了这个方法的话,比如各种__call,__get,__set以及constructor,destructor方法等。 */
}
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); /* 最后,将类添加到runtime 的全局class_table这个HashTable中,这里将类名转成lowercase的了,所以类名不区分大小写 */
free(lowercase_name);
return class_entry;
}
到这里,也就完成类的注册了...