内容均以php5.6.14为例.

扩展中定义一个类有以下四步:

  1. #1. 声明一个存储类信息的指针.
  2.  
  3. zend_class_entry *errs_ce;
  4.  
  5. #2. 定义方法的参数信息,类的方法实现.
  6.  
  7. ZEND_BEGIN_ARG_INFO_EX(errs_test_arginfo, , , )
  8. ZEND_ARG_INFO(, arg)
  9. ZEND_END_ARG_INFO()
  10.  
  11. PHP_METHOD(errs, test) {
  12. }
  13.  
  14. #3. 声明一个含有类方法信息的数组; 统一用含有三个NULL的数组结尾.
  15.  
  16. zend_function_entry errs_methods[] = {
  17. PHP_ME(errs, test, errs_test_arginfo, ZEND_ACC_PUBLIC)
  18. {NULL, NULL, NULL}
  19. }; /* 注意 errs_methods 结尾要加分号。 */
  20.  
  21. #4. 模块初始化 MINIT 中注册.
  22.  
  23. PHP_MINIT_FUNCTION(testmodule)
  24. {
  25. zend_class_entry ce;
        /* init class entry */
  26. INIT_CLASS_ENTRY(ce, "errs", errs_methods);
        /* register */
  27. errs_ce = zend_register_internal_class(&ce TSRMLS_CC);
        /* flags */
  28. errs_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
  29.  
  30. return SUCCESS;
  31. }

zend_class_entry 是实现PHP类和对象的基础结构类型。

./Zend/zend.h:302

  1. /*
  2. * zval
  3. */
  4. typedef struct _zend_class_entry zend_class_entry;
  5.  
  6. ....
  7.  
  8. struct _zend_class_entry {
  9. char type;
  10. const char *name;
  11. zend_uint name_length;
  12. struct _zend_class_entry *parent;
  13. int refcount;
  14. zend_uint ce_flags;
  15.  
  16. HashTable function_table;
  17. HashTable properties_info;
  18. zval **default_properties_table;
  19. zval **default_static_members_table;
  20. zval **static_members_table;
  21. HashTable constants_table;
  22. int default_properties_count;
  23. int default_static_members_count;
  24.  
  25. union _zend_function *constructor;
  26. union _zend_function *destructor;
  27. union _zend_function *clone;
  28. union _zend_function *__get;
  29. union _zend_function *__set;
  30. union _zend_function *__unset;
  31. union _zend_function *__isset;
  32. union _zend_function *__call;
  33. union _zend_function *__callstatic;
  34. union _zend_function *__tostring;
  35. union _zend_function *__debugInfo;
  36. union _zend_function *serialize_func;
  37. union _zend_function *unserialize_func;
  38.  
  39. zend_class_iterator_funcs iterator_funcs;
  40.  
  41. /* handlers */
  42. zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
  43. zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
  44. int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* a class implements this interface */
  45. union _zend_function *(*get_static_method)(zend_class_entry *ce, char* method, int method_len TSRMLS_DC);
  46.  
  47. /* serializer callbacks */
  48. int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
  49. int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
  50.  
  51. zend_class_entry **interfaces;
  52. zend_uint num_interfaces;
  53.  
  54. zend_class_entry **traits;
  55. zend_uint num_traits;
  56. zend_trait_alias **trait_aliases;
  57. zend_trait_precedence **trait_precedences;
  58.  
  59. union {
  60. struct {
  61. const char *filename;
  62. zend_uint line_start;
  63. zend_uint line_end;
  64. const char *doc_comment;
  65. zend_uint doc_comment_len;
  66. } user;
  67. struct {
  68. const struct _zend_function_entry *builtin_functions;
  69. struct _zend_module_entry *module;
  70. } internal;
  71. } info;
  72. };

定义参数信息的宏。

./Zend/zend_API.h:108

  1. #define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 0 },

  2. ...
  3.  
  4. #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
  5. static const zend_arg_info name[] = { \
  6. { NULL, , NULL, required_num_args, , return_reference, , },
  7. #define ZEND_BEGIN_ARG_INFO(name, _unused) \
  8. ZEND_BEGIN_ARG_INFO_EX(name, , ZEND_RETURN_VALUE, -)
  9. #define ZEND_END_ARG_INFO() };

ZEND_BEGIN_ARG_INFO_EX() 的四个参数含义:

  name: 类名_方法名_arginfo

  _unused: 0

  return_reference: 0

  required_num_args: 这个函数必要的参数数量是几个

ZEND_ARG_INFO() 的两个参数含义:

pass_by_ref: 0

name: 形参名

./Zend/zend_API.h:35

  1. typedef struct _zend_function_entry {
  2. const char *fname;
  3. void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
  4. const struct _zend_arg_info *arg_info;
  5. zend_uint num_args;
  6. zend_uint flags;
  7. } zend_function_entry;
  1. #define INIT_CLASS_ENTRY(class_container, class_name, functions) \
  2. INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
  3.  
  4. #define INIT_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions) \
  5. INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, NULL, NULL, NULL, NULL, NULL)
  6.  
  7. #define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
  8. { \
  9. const char *cl_name = class_name; \
  10. int _len = class_name_len; \
  11. class_container.name = zend_new_interned_string(cl_name, _len+, TSRMLS_CC); \
  12. if (class_container.name == cl_name) { \
  13. class_container.name = zend_strndup(cl_name, _len); \
  14. } \
  15. class_container.name_length = _len; \
  16. INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
  17. }
  18. ....
  19.  
  20. #define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \
  21. INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, sizeof(class_name)-, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL)

类的定义,接口定义,属性操作,数组操作的函数原型。

./Zend/zend_API.h: 268~457

  1. ....
  2.  
  3. ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);
  4. ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC);
  5. ZEND_API int zend_startup_module(zend_module_entry *module_entry);
  6. ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module_entry TSRMLS_DC);
  7. ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC);
  8. ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC);
  9. ZEND_API int zend_startup_modules(TSRMLS_D);
  10. ZEND_API void zend_collect_module_handlers(TSRMLS_D);
  11. ZEND_API void zend_destroy_modules(void);
  12. ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC);
  13.  
  14. // 注册一个"类"
  15. ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC);

  16. // 注册一个"子类";第二个,第三个参数都为 NULL 时,等同于 zend_register_internal_class.
  17. ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC);

  18. // 注册一个"接口"
  19. ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC);
  20. ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...);
  21.  
  22. ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC);
  23.  
  24. #define zend_register_class_alias(name, ce) \
  25. zend_register_class_alias_ex(name, sizeof(name)-, ce TSRMLS_CC)
  26. #define zend_register_ns_class_alias(ns, name, ce) \
  27. zend_register_class_alias_ex(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name))-, ce TSRMLS_CC)
  28.  
  29. ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC);
  30. ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC);
  31.  
  32. ZEND_API void zend_wrong_param_count(TSRMLS_D);
  33.  
  34. #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0)
  35. #define IS_CALLABLE_CHECK_NO_ACCESS (1<<1)
  36. #define IS_CALLABLE_CHECK_IS_STATIC (1<<2)
  37. #define IS_CALLABLE_CHECK_SILENT (1<<3)
  38.  
  39. #define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC)
  40.  
  41. ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC);
  42. ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC);
  43. ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC);
  44. ZEND_API const char *zend_get_module_version(const char *module_name);
  45. ZEND_API int zend_get_module_started(const char *module_name);
  46. ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC);
  47. 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);

  48. // 定义类属性,zend_declare_property_*
  49. ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC);
  50. ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
  51. ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
  52. ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC);
  53. 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);
  54. 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);
  55.  
  56. // 定义类常量,zend_declare_class_constant_*
  57. ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC);
  58. ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC);
  59. ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC);
  60. ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC);
  61. ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC);
  62. 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);
  63. ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC);
  64.  
  65. // 更新类常量,zend_update_class_constants_*
  66. ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
  67. ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC);
  68. ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
  69. ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
  70. ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
  71. ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
  72. ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
  73. 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);
  74.  
  75. // 更新类静态属性,zend_update_static_property_*
  76. ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
  77. ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC);
  78. ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
  79. ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
  80. ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
  81. ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
  82. 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);
  83.  
  84. // 读取类属性
  85. ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC);
  86. // 读取类静态属性,与object无关
  87. ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC);
  88.  
  89. ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC);
  90. ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC);
  91. ZEND_API char *zend_get_type_by_const(int type);
  92.  
  93. #define getThis() (this_ptr)
  94.  
  95. #define WRONG_PARAM_COUNT ZEND_WRONG_PARAM_COUNT()
  96. #define WRONG_PARAM_COUNT_WITH_RETVAL(ret) ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret)
  97. #define ARG_COUNT(dummy) (ht)
  98. #define ZEND_NUM_ARGS() (ht)
  99. #define ZEND_WRONG_PARAM_COUNT() { zend_wrong_param_count(TSRMLS_C); return; }
  100. #define ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret) { zend_wrong_param_count(TSRMLS_C); return ret; }
  101.  
  102. #ifndef ZEND_WIN32
  103. #define DLEXPORT
  104. #endif
  105.  
  106. // 初始化一个数组
  107. #define array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC)
  108. #define array_init_size(arg, size) _array_init((arg), (size) ZEND_FILE_LINE_CC)
  109. // 初始化一个对象
  110. #define object_init(arg) _object_init((arg) ZEND_FILE_LINE_CC TSRMLS_CC)
  111. #define object_init_ex(arg, ce) _object_init_ex((arg), (ce) ZEND_FILE_LINE_CC TSRMLS_CC)
  112. #define object_and_properties_init(arg, ce, properties) _object_and_properties_init((arg), (ce), (properties) ZEND_FILE_LINE_CC TSRMLS_CC)
  113. ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC);
  114. ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC);
  115. ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC);
  116. ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC);
  117. ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);
  118.  
  119. ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);
  120.  
  121. /* no longer supported */
  122. ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS));
  123.  
  124. ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n);
  125. ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len);
  126. ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b);
  127. ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r);
  128. ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d);
  129. ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate);
  130. ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate);
  131. ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value);
  132.  
  133. // 添加关联数组值,add_assoc_*
  134. #define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key)+1, __n)
  135. #define add_assoc_null(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key) + 1)
  136. #define add_assoc_bool(__arg, __key, __b) add_assoc_bool_ex(__arg, __key, strlen(__key)+1, __b)
  137. #define add_assoc_resource(__arg, __key, __r) add_assoc_resource_ex(__arg, __key, strlen(__key)+1, __r)
  138. #define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key)+1, __d)
  139. #define add_assoc_string(__arg, __key, __str, __duplicate) add_assoc_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)
  140. #define add_assoc_stringl(__arg, __key, __str, __length, __duplicate) add_assoc_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)
  141. #define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key)+1, __value)
  142.  
  143. /* unset() functions are only suported for legacy modules and null() functions should be used */
  144. #define add_assoc_unset(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key) + 1)
  145. #define add_index_unset(__arg, __key) add_index_null(__arg, __key)
  146. #define add_next_index_unset(__arg) add_next_index_null(__arg)
  147. #define add_property_unset(__arg, __key) add_property_null(__arg, __key)
  148.  
  149. // 添加索引数组值,add_index_*
  150. ZEND_API int add_index_long(zval *arg, ulong idx, long n);
  151. ZEND_API int add_index_null(zval *arg, ulong idx);
  152. ZEND_API int add_index_bool(zval *arg, ulong idx, int b);
  153. ZEND_API int add_index_resource(zval *arg, ulong idx, int r);
  154. ZEND_API int add_index_double(zval *arg, ulong idx, double d);
  155. ZEND_API int add_index_string(zval *arg, ulong idx, const char *str, int duplicate);
  156. ZEND_API int add_index_stringl(zval *arg, ulong idx, const char *str, uint length, int duplicate);
  157. ZEND_API int add_index_zval(zval *arg, ulong index, zval *value);
  158.  
  159. // 添加索引数组值 索引自增,add_next_index_*
  160. ZEND_API int add_next_index_long(zval *arg, long n);
  161. ZEND_API int add_next_index_null(zval *arg);
  162. ZEND_API int add_next_index_bool(zval *arg, int b);
  163. ZEND_API int add_next_index_resource(zval *arg, int r);
  164. ZEND_API int add_next_index_double(zval *arg, double d);
  165. ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate);
  166. ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate);
  167. ZEND_API int add_next_index_zval(zval *arg, zval *value);
  168.  
  169. ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate);
  170. ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate);
  171.  
  172. #define add_get_assoc_string(__arg, __key, __str, __dest, __duplicate) add_get_assoc_string_ex(__arg, __key, strlen(__key)+1, __str, __dest, __duplicate)
  173. #define add_get_assoc_stringl(__arg, __key, __str, __length, __dest, __duplicate) add_get_assoc_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __dest, __duplicate)
  174.  
  175. ZEND_API int add_get_index_long(zval *arg, ulong idx, long l, void **dest);
  176. ZEND_API int add_get_index_double(zval *arg, ulong idx, double d, void **dest);
  177. ZEND_API int add_get_index_string(zval *arg, ulong idx, const char *str, void **dest, int duplicate);
  178. ZEND_API int add_get_index_stringl(zval *arg, ulong idx, const char *str, uint length, void **dest, int duplicate);
  179.  
  180. ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value);
  181.  
  182. ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long l TSRMLS_DC);
  183. ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC);
  184. ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC);
  185. ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long r TSRMLS_DC);
  186. ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC);
  187. ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate TSRMLS_DC);
  188. ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, int duplicate TSRMLS_DC);
  189. ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC);
  190.  
  191. // 添加类属性 add_property_*
  192. #define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key)+1, __n TSRMLS_CC)
  193. #define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key) + 1 TSRMLS_CC)
  194. #define add_property_bool(__arg, __key, __b) add_property_bool_ex(__arg, __key, strlen(__key)+1, __b TSRMLS_CC)
  195. #define add_property_resource(__arg, __key, __r) add_property_resource_ex(__arg, __key, strlen(__key)+1, __r TSRMLS_CC)
  196. #define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key)+1, __d TSRMLS_CC)
  197. #define add_property_string(__arg, __key, __str, __duplicate) add_property_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate TSRMLS_CC)
  198. #define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC)
  199. #define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC)
  200.  
  201. // call_user_function
  202. ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);
  203. ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval ** params[], int no_separation, HashTable *symbol_table TSRMLS_DC);
  204.  
  205. ZEND_API extern const zend_fcall_info empty_fcall_info;
  206. ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache;
  207.  
  208. ....

关于 zend_read_static_property 的 silent 参数,因为是 zend_std_get_static_property 的封装,

所以我们应该看 zend_std_get_static_property 的实现。

./Zend/zend_object_handlers.c:1281

  1. if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+, hash_value, (void **) &property_info)==FAILURE)) {
  2. if (!silent) {
  3. zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
  4. }
  5. return NULL;
  6. }

函数中有这么一段,如果没有找到属性的时候,silent=0 报 E_ERROR,silent=1 忽略报错。

HashTable 的底层函数,数组操作其实是对它们的再封装。

./Zend/zend_hash.h:100

  1. /* startup/shutdown */
  2. ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
  3. ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
  4. ZEND_API void zend_hash_destroy(HashTable *ht);
  5. ZEND_API void zend_hash_clean(HashTable *ht);
  6. #define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
  7. #define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
  8.  
  9. /* additions/updates/changes */
  10. ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
  11. #define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
  12. _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
  13. #define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
  14. _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
  15.  
  16. ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
  17. #define zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
  18. _zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
  19. #define zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
  20. _zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
  21.  
  22. ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
  23. #define zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
  24. _zend_hash_index_update_or_next_insert(ht, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
  25. #define zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
  26. _zend_hash_index_update_or_next_insert(ht, , pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
  27.  
  28. ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength);
  29.  
  30. ....
  31.  
  32. /* Deletes */
  33. ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag);
  34. #define zend_hash_del(ht, arKey, nKeyLength) \
  35. zend_hash_del_key_or_index(ht, arKey, nKeyLength, , HASH_DEL_KEY)
  36. #define zend_hash_quick_del(ht, arKey, nKeyLength, h) \
  37. zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK)
  38. #define zend_hash_index_del(ht, h) \
  39. zend_hash_del_key_or_index(ht, NULL, , h, HASH_DEL_INDEX)
  40. #define zend_get_hash_value \
  41. zend_hash_func
  42.  
  43. /* Data retreival */
  44. ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
  45. ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void ** pData);
  46. ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData);
  47.  
  48. /* Misc */
  49. ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength);
  50. ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h);
  51. ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
  52. ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);

类与方法的访问权限修饰符,ZEND_ACC_* 。

./Zend/zend_compile.h:150

  1. ...
  2.  
  3. /* method flags (types) */
  4. #define ZEND_ACC_STATIC 0x01
  5. #define ZEND_ACC_ABSTRACT 0x02
  6. #define ZEND_ACC_FINAL 0x04
  7. #define ZEND_ACC_IMPLEMENTED_ABSTRACT 0x08
  8.  
  9. /* class flags (types) */
  10. /* ZEND_ACC_IMPLICIT_ABSTRACT_CLASS is used for abstract classes (since it is set by any abstract method even interfaces MAY have it set, too). */
  11. /* ZEND_ACC_EXPLICIT_ABSTRACT_CLASS denotes that a class was explicitly defined as abstract by using the keyword. */
  12. #define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS 0x10
  13. #define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20
  14. #define ZEND_ACC_FINAL_CLASS 0x40
  15. #define ZEND_ACC_INTERFACE 0x80
  16. #define ZEND_ACC_TRAIT 0x120
  17.  
  18. /* op_array flags */
  19. #define ZEND_ACC_INTERACTIVE 0x10
  20.  
  21. /* method flags (visibility) */
  22. /* The order of those must be kept - public < protected < private */
  23. #define ZEND_ACC_PUBLIC 0x100
  24. #define ZEND_ACC_PROTECTED 0x200
  25. #define ZEND_ACC_PRIVATE 0x400
  26. #define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)
  27.  
  28. #define ZEND_ACC_CHANGED 0x800
  29. #define ZEND_ACC_IMPLICIT_PUBLIC 0x1000
  30.  
  31. /* method flags (special method detection) */
  32. #define ZEND_ACC_CTOR 0x2000
  33. #define ZEND_ACC_DTOR 0x4000
  34. #define ZEND_ACC_CLONE 0x8000
  35.  
  36. /* method flag (bc only), any method that has this flag can be used statically and non statically. */
  37. #define ZEND_ACC_ALLOW_STATIC 0x10000
  38.  
  39. /* shadow of parent's private method/property */
  40. #define ZEND_ACC_SHADOW 0x20000
  41.  
  42. /* deprecation flag */
  43. #define ZEND_ACC_DEPRECATED 0x40000
  44.  
  45. /* class implement interface(s) flag */
  46. #define ZEND_ACC_IMPLEMENT_INTERFACES 0x80000
  47. #define ZEND_ACC_IMPLEMENT_TRAITS 0x400000
  48.  
  49. /* class constants updated */
  50. #define ZEND_ACC_CONSTANTS_UPDATED 0x100000
  51.  
  52. /* user class has methods with static variables */
  53. #define ZEND_HAS_STATIC_IN_METHODS 0x800000
  54.  
  55. #define ZEND_ACC_CLOSURE 0x100000
  56. #define ZEND_ACC_GENERATOR 0x800000
  57.  
  58. /* function flag for internal user call handlers __call, __callstatic */
  59. #define ZEND_ACC_CALL_VIA_HANDLER 0x200000
  60.  
  61. /* disable inline caching */
  62. #define ZEND_ACC_NEVER_CACHE 0x400000
  63.  
  64. #define ZEND_ACC_VARIADIC 0x1000000
  65.  
  66. #define ZEND_ACC_RETURN_REFERENCE 0x4000000
  67. #define ZEND_ACC_DONE_PASS_TWO 0x8000000
  68.  
  69. /* function has arguments with type hinting */
  70. #define ZEND_ACC_HAS_TYPE_HINTS 0x10000000
  71.  
  72. ...

例:定义一个接口,实现接口的父类,继承父类的子类.

  1. zend_class_entry *theinterface_ce, *parentclass_ce, *childclass_ce;
  2.  
  3. zend_function_entry theinterface_methods[] = {
  4.   ZEND_ABSTRACT_ME(theinterface, hello, NULL) // 这里不需要第四个参数(访问权限)
  5.   {NULL, NULL, NULL}
  6. };
  7.  
  8. zend_function_entry parentclass_methods[] = {
  9. ZEND_ME(parentclass_ce, hello, NULL, ZEND_ACC_PUBLIC)
  10.   {NULL, NULL, NULL}
  11. };
  12.  
  13. zend_function_entry childclass_methods[] = {
  14.   ZEND_ME(childclass_ce, index, NULL, ZEND_ACC_PUBLIC)
  15.   {NULL, NULL, NULL}
  16. };
  17.  
  18. PHP_MINIT_FUNCTION(test) {
  19.   zend_class_entry ce, p_ce, c_ce;
  20.   INIT_CLASS_ENTRY(ce, "theinterface", theinterface_methods);
  21.   theinterface_ce = zend_register_internal_interface(&ce TSRMLS_CC);
  22.  
  23. // 实现theinterface接口的parentclass类
  24.   INIT_CLASS_ENTRY(p_ce, "parentclass", parentclass_methods);
  25.   parentclass_ce = zend_register_internal_class(&p_ce TSRMLS_CC);
  26.   zend_class_implements(&p_ce TSRMLS_CC, , theinterface_ce);
  27.  
  28. // 定义parentclass的子类childclass
  29.   INIT_CLASS_ENTRY(c_ce, "childclass", childclass_methods);
  30.   childclass_ce = zend_register_internal_class_ex(&c_ce, &parentclass, "parentclass" TSRMLS_CC);
  31.   childclass_cd->ce_flags |= ZEND_ACC_FINAL_CLASS;
  32.   
  33.   return SUCCESS;
  34. }

./Zend/zend_API.h 包含使用到的宏和函数原型,主要看有哪些参数和参数格式:

  1. #define ZEND_ABSTRACT_ME(classname, name, arg_info) ZEND_FENTRY(name, NULL, arg_info, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
  1. #define ZEND_ME(classname, name, arg_info, flags) ZEND_FENTRY(name, ZEND_MN(classname##_##name), arg_info, flags)
  1. #define INIT_CLASS_ENTRY(class_container, class_name, functions) \
  2. INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
  1. ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC);
  1. ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC);
  1. ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...);
  1. ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC);

Link: http://www.cnblogs.com/farwish/p/5631605.html

[php-src]窥探Php内核中的数组与面向对象的更多相关文章

  1. [php-src]窥探Php内核中的变量

    内容均以php-5.6.14为例. 在看各种组合数据类型之前,有必要先熟悉下 Zend/zend_types.h 里面的自定义数据类型. #ifndef ZEND_TYPES_H // 防止多次 in ...

  2. [php-src]理解Php内核中的函数与INI

    内容均以php-5.6.14为例. 一. 函数结构 内核中定义一个php函数使用 PHP_FUNCTION 宏 包装,扩展也不例外,该宏在 ./main/php.h:343 有着一系列类似以 PHP ...

  3. [翻译] Linux 内核中的位数组和位操作

    目录 Linux 内核里的数据结构 原文链接与说明 Linux 内核中的位数组和位操作 位数组声明 体系结构特定的位操作 通用位操作 链接 Linux 内核里的数据结构 原文链接与说明 https:/ ...

  4. 操作系统---在内核中重新加载GDT和堆栈

    摘要 用BIOS方式启动计算机后,BIOS先读取引导扇区,引导扇区再从外部存储设备中读取加载器,加载器读取内核.进入内核后,把加载器中建立的GDT复制到内核中. 这篇文章的最大价值也许在末尾,对C语言 ...

  5. Linux 2.6内核中新的锁机制--RCU

    转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁 ...

  6. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  7. GCC 中零长数组与变长数组

    前两天看程序,发现在某个函数中有下面这段程序: int n; //define a variable n int array[n]; //define an array with length n 在 ...

  8. Javascript中判断数组的正确姿势

    在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...

  9. 内核中用于数据接收的结构体struct msghdr(转)

    内核中用于数据接收的结构体struct msghdr(转) 我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,pin ...

随机推荐

  1. Flume整合Spark Streaming

    Spark版本1.5.2,Flume版本:1.6 Flume agent配置文件:spool-8.51.conf agent.sources = source1 agent.channels = me ...

  2. weedfs getsockopt: connection timed out

    启动master weed master -ip 10.191.197.133 -mdir /namenode -ip.bind 10.191.197.133 I0809 16:53:51 7721 ...

  3. R 统计学工具部署和使用

    由于公司内部对于市场数据分析的需求,要求引入R统计工具,并集成到报表工具中.对于R的介绍,大家请百度一下,当然,最好能去看官方的说明 https://www.r-project.org/ 下面简单介绍 ...

  4. VMware 虚拟机桥接网络设置

    一.桥接的基本原理    配置成桥接网络连接模式的虚拟机就当作主机所在以太网的一部分,虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑,可以像主机一样可以访问以太网中的所有共享资源和网络连 ...

  5. CheckBox设置Enabled为False后,无法修改ForeColor

    设置CheckBox的AutoCheck为False,Enabled为True,即可解决.

  6. 在指定时间干,必须干(kbmmw 中的事件调度)

    从去年开始,kbmmw 慢慢增加内涵,除了完善各种服务外,陆续增加和扩展了作为一个中间件必须有的功能, 例如,权限管理.日志系统.调度系统.内存调试等功能. 今天给大家介绍一下kbmmw 的调度事件, ...

  7. jenkins调度selenium脚本不打开浏览器解决办法

    原文地址: http://blog.csdn.net/achang21/article/details/45096003 The web browser doesn't show while run ...

  8. javascript 零星知识点

    通过js动态生成的元素绑定事件.不能通过js获取元素对象,并赋予事件,最简捷的途径就是将事件直接添加到属性中(DOM0);

  9. JSON与XML优缺点对比分析

    本文从各个方面向大家对比展示了json和xml的优缺点,十分的全面细致,有需要的小伙伴可以参考下. 1. 定义介绍 1.1 XML定义 扩展标记语言 (Extensible Markup Langua ...

  10. 设计winform自带动态加载工具按钮和实现热键响应

    1.初衷 主要是想设计一个自带添加工具按钮和按钮的快捷键的基窗体.这样以后所设计的窗体只要继承自这个窗体就可以实现热键响应和动态加工具按钮的功能了 写这边文章主要是为了以后使用的时候有个参考,因为这只 ...