想法 我以前对于 C 语言的印象是有很强的确定性,而 PHP 在执行的时候会被翻译为 C 语言执行,所以一直很好奇 PHP 怎么调用底层函数。 换句话说就是已知函数名字
函数的注册 调用顺序为: 1 2 3 4 5 6 7 - main -- php_cli_startup --- php_module_startup ---- zend_startup ----- zend_startup_builtin_function ------ zend_register_module_ex(*module) ------- zend_register_functions(module->functions) sapi/cli/php_cli.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int main(int argc, char *argv[]) { // ... sapi_module_struct *sapi_module = &cli_sapi_module; // ... /* startup after we get the
ext/standard/array.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /* {{{ proto bool sort(array &array_arg [, int sort_flags]) Sort an array */ PHP_FUNCTION(sort) { zval *array; zend_long sort_type = PHP_SORT_REGULAR; compare_func_t cmp; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ARRAY_EX(array, 0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(sort_type) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); cmp = php_get_data_compare_func(sort_type, 0); // 根据 sort_flags 选择比较函数 if (zend_hash_sort(Z_ARRVAL_P(array), cmp,
从数组入手。 数组相关函数是 PHP 扩展的一部分,扩展名为 standard,执行 php -m 可以看到该扩展。 该扩展的源码在 PHP 源码包的 ext/standard ,其中数组相关函数的定
创建对象: zend_objects.c 1 2 3 4 5 6 7 8 ZEND_API zend_object* ZEND_FASTCALL zend_objects_new(zend_class_entry *ce) { zend_object *object = emalloc(sizeof(zend_object) + zend_object_properties_size(ce)); _zend_object_std_init(object, ce); object->handlers = &std_object_handlers; return object; } zend_object_handlers.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ZEND_API const
每个值容器(zend_value)里面都会有引用计数结构体 zend_rrefcounted 引用计数减少到 0 时进行清除 unset() 将值的引用减少 1 值容器引用在减少 1 后如果不为 0 ,则加