# php 扩展开发 **Repository Path**: dddxiu/phpextended_development ## Basic Information - **Project Name**: php 扩展开发 - **Description**: No description available - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-04-30 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # php 扩展开发 ### PHP 的函数注册 ``` # 声明参数.也可写在函数体中 ZEND_BEGIN_ARG_INFO_EX(arginfo_celsius_to_fahrenheit, 0, 0, 1) ZEND_ARG_INFO(0, celsius) ZEND_END_ARG_INFO(); static double php_celsius_to_fahrenheit(double c) { return (((double)9/5) * c) + 32 ; } # 声明函数 PHP_FUNCTION(celsius_to_fahrenheit) { double c; if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &c) == FAILURE) { return; } RETURN_DOUBLE(php_celsius_to_fahrenheit(c)); } # 注册模块函数 static const zend_function_entry pib_functions[] = { PHP_FE(fahrenheit_to_celsius, arginfo_fahrenheit_to_celsius) PHP_FE(celsius_to_fahrenheit, arginfo_celsius_to_fahrenheit) PHP_FE_END }; ``` | 参数宏 | 含义 | |---|---| |Z_PARAM_ARRAY() | /* old "a" */ | |Z_PARAM_ARRAY_OR_OBJECT() | /* old "A" */ | |Z_PARAM_BOOL() | /* old "b" */ | |Z_PARAM_CLASS() | /* old "C" */ | |Z_PARAM_DOUBLE() | /* old "d" */ | |Z_PARAM_FUNC() | /* old "f" */ | |Z_PARAM_ARRAY_HT() | /* old "h" */ | |Z_PARAM_ARRAY_OR_OBJECT_HT() | /* old "H" */ | |Z_PARAM_LONG() | /* old "l" */ | |Z_PARAM_STRICT_LONG() | /* old "L" */ | |Z_PARAM_OBJECT() | /* old "o" */ | |Z_PARAM_OBJECT_OF_CLASS() | /* old "O" */ | |Z_PARAM_PATH() | /* old "p" */ | |Z_PARAM_PATH_STR() | /* old "P" */ | |Z_PARAM_RESOURCE() | /* old "r" */ | |Z_PARAM_STRING() | /* old "s" */ | |Z_PARAM_STR() | /* old "S" */ | |Z_PARAM_ZVAL() | /* old "z" */ | |Z_PARAM_VARIADIC() | /* old "+" and "*" */ | [php_functions](http://www.phpinternalsbook.com/php7/extensions_design/php_functions.html) [参数声明](http://www.phpinternalsbook.com/php7/extensions_design/php_functions.html#declaring-function-arguments) ### 模块的常量定义 ``` #define TEMP_CONVERTER_TO_FAHRENHEIT 2 #define TEMP_CONVERTER_TO_CELSIUS 1 PHP_MINIT_FUNCTION(pib) { REGISTER_LONG_CONSTANT("TEMP_CONVERTER_TO_CELSIUS", TEMP_CONVERTER_TO_CELSIUS, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("TEMP_CONVERTER_TO_FAHRENHEIT", TEMP_CONVERTER_TO_FAHRENHEIT, CONST_CS|CONST_PERSISTENT); return SUCCESS; } ``` ### PHP_ARRAY 处理 ``` ZEND_BEGIN_ARG_INFO_EX(arginfo_multiple_fahrenheit_to_celsius, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, temperatures, 0) ZEND_END_ARG_INFO(); static const zend_function_entry pib_functions[] = { /* ... */ PHP_FE(multiple_fahrenheit_to_celsius, arginfo_multiple_fahrenheit_to_celsius) PHP_FE_END }; PHP_FUNCTION(multiple_fahrenheit_to_celsius) { HashTable *temperatures; zval *data; if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &temperatures) == FAILURE) { return; } if (zend_hash_num_elements(temperatures) == 0) { return; } array_init_size(return_value, zend_hash_num_elements(temperatures)); ZEND_HASH_FOREACH_VAL(temperatures, data) zval dup; ZVAL_COPY_VALUE(&dup, data); convert_to_double(&dup); add_next_index_double(return_value, php_fahrenheit_to_celsius(Z_DVAL(dup))); ZEND_HASH_FOREACH_END(); } ``` ### PHP的引用传参 ``` ZEND_BEGIN_ARG_INFO_EX(arginfo_fahrenheit_to_celsius, 0, 0, 1) ZEND_ARG_INFO(1, fahrenheit) # 1:引用传参,0:非引用传参 ZEND_END_ARG_INFO(); PHP_FUNCTION(fahrenheit_to_celsius) { double result; zval *param; # 引用传参需要通过zval来接收,且参数字符为"z" if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", ¶m) == FAILURE) { return; } ZVAL_DEREF(param); convert_to_double(param); ZVAL_DOUBLE(param, php_fahrenheit_to_celsius(Z_DVAL_P(param))); } ``` ### 管理全局资源 TSRM (Thread Safe Resource Manager) ``` ZEND_BEGIN_MODULE_GLOBALS(pib) zend_long rnd; zend_ulong cur_score; zval scores; ZEND_END_MODULE_GLOBALS(pib) ZEND_DECLARE_MODULE_GLOBALS(pib) static void pib_rnd_init(void) { /* reset current score as well */ PIB_G(cur_score) = 0; php_random_int(0, 100, &PIB_G(rnd), 0); } PHP_GINIT_FUNCTION(pib) { /* ZEND_SECURE_ZERO is a memset(0). Could resolve to bzero() as well */ ZEND_SECURE_ZERO(pib_globals, sizeof(*pib_globals)); } ZEND_BEGIN_ARG_INFO_EX(arginfo_guess, 0, 0, 1) ZEND_ARG_INFO(0, num) ZEND_END_ARG_INFO() PHP_RINIT_FUNCTION(pib) { array_init(&PIB_G(scores)); pib_rnd_init(); return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(pib) { zval_dtor(&PIB_G(scores)); return SUCCESS; } PHP_FUNCTION(pib_guess) { zend_long r; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &r) == FAILURE) { return; } if (r == PIB_G(rnd)) { add_next_index_long(&PIB_G(scores), PIB_G(cur_score)); pib_rnd_init(); RETURN_TRUE; } PIB_G(cur_score)++; if (r < PIB_G(rnd)) { RETURN_STRING("more"); } RETURN_STRING("less"); } PHP_FUNCTION(pib_get_scores) { if (zend_parse_parameters_none() == FAILURE) { return; } RETVAL_ZVAL(&PIB_G(scores), 1, 0); } PHP_FUNCTION(pib_reset) { if (zend_parse_parameters_none() == FAILURE) { return; } pib_rnd_init(); } static const zend_function_entry func[] = { PHP_FE(pib_reset, NULL) PHP_FE(pib_get_scores, NULL) PHP_FE(pib_guess, arginfo_guess) PHP_FE_END }; zend_module_entry pib_module_entry = { STANDARD_MODULE_HEADER, "pib", func, /* Function entries */ NULL, /* Module init */ NULL, /* Module shutdown */ PHP_RINIT(pib), /* Request init */ PHP_RSHUTDOWN(pib), /* Request shutdown */ NULL, /* Module information */ "0.1", /* Replace with version number for your extension */ PHP_MODULE_GLOBALS(pib), PHP_GINIT(pib), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; ``` ### phpinfo ``` #include "php/main/SAPI.h" #include "ext/standard/info.h" #define PIB_TXT "PHPInternalsBook Authors" #define PIB_HTML "

" PIB_TXT "

" PHP_MINFO_FUNCTION(pib) { time_t t; char cur_time[32]; time(&t); php_asctime_r(localtime(&t), cur_time); php_info_print_table_start(); php_info_print_table_colspan_header(2, "PHPInternalsBook"); php_info_print_table_row(2, "Current time", cur_time); php_info_print_table_end(); php_info_print_box_start(0); if (!sapi_module.phpinfo_as_text) { php_write(PIB_HTML, strlen(PIB_HTML)); } else { php_write(PIB_TXT, strlen(PIB_TXT)); } php_info_print_box_end(); } zend_module_entry pib_module_entry = { STANDARD_MODULE_HEADER, "pib", NULL, /* Function entries */ NULL, /* Module init */ NULL, /* Module shutdown */ NULL, /* Request init */ NULL, /* Request shutdown */ PHP_MINFO(pib), /* Module information */ "0.1", /* Replace with version number for your extension */ STANDARD_MODULE_PROPERTIES }; ``` [php 扩展开发](http://www.phpinternalsbook.com/php7/extensions_design.html) ### 注册类 #### 注册空类 ``` PHP_MINIT_FUNCTION(study) { init_class(); return SUCCESS; } PHP_METHOD(study_ext_class,print) { php_printf("你调用了study_ext_class的print方法\n"); } const zend_function_entry study_class_method[]={ # ZEND_BEGIN_ARG_INFO_EX(democlass_sayhello_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO(); 为第三个参数提示功能 # 添加该段代码之后,需要修改PHP_ME函数的第三个参数NULL为democlass_sayhello_args PHP_ME(study_ext_class,print,NULL,ZEND_ACC_PUBLIC) PHP_FE_END }; zend_class_entry *study_ce; void init_class(){ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "study_ext_class" , study_class_method); study_ce = zend_register_internal_class(&ce); } ``` ``` PHP_ME( Test, protectedFinalStaticMethod, arginfo_xyz, ZEND_ACC_PROTECTED | ZEND_ACC_FINAL | ZEND_ACC_STATIC ) ``` #### 注册属性 ``` # init_class 注册 zend_declare_property_long(php_democlass_entry, "age", sizeof("age") - 1, 24, ZEND_ACC_PUBLIC TSRMLS_CC); ``` ``` # 可用修饰器 ZEND_ACC_PUBLIC ZEND_ACC_PROTECTED ZEND_ACC_PRIVATE ZEND_ACC_STATIC ZEND_ACC_FINAL ZEND_ACC_ABSTRACT ``` | 类型| 描述 | |---|---| ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC);|property ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC);|property_ex ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC);|property_null ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);|property_bool ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);|property_long ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);|property_double ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);|property_string ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC);|property_stringl #### 修改属性值 ``` /* zend_API.h 326-328 */ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC); ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC); ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC); /* 下面这个是zend_update_property_*系列函数,与declare系列类似,不做详述,参考zend_API.h 309-328 */ ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC); ``` #### 完整的例子 ``` PHP_METHOD(Test, getFoo) { zval *obj, *foo_value; if (zend_parse_parameters_none() == FAILURE) { return; } obj = getThis(); foo_value = zend_read_property(test_ce, obj, "foo", sizeof("foo") - 1, 1 TSRMLS_CC); RETURN_ZVAL(foo_value, 1, 0); } PHP_METHOD(Test, setFoo) { zval *obj, *new_foo_value; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &new_foo_value) == FAILURE) { return; } obj = getThis(); zend_update_property(test_ce, obj, "foo", sizeof("foo") - 1, new_foo_value TSRMLS_CC); } // ... ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_set, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() // ... PHP_ME(Test, getFoo, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(Test, setFoo, arginfo_set, ZEND_ACC_PUBLIC) // ... ``` - [https://blog.icodef.com/2018/09/25/1508](https://blog.icodef.com/2018/09/25/1508) - [https://cloud.tencent.com/developer/article/1396007](https://cloud.tencent.com/developer/article/1396007) - [http://www.phpinternalsbook.com/classes_objects/simple_classes.html#inheritance-and-interfaces](http://www.phpinternalsbook.com/classes_objects/simple_classes.html#inheritance-and-interfaces)