【PHP 源码】PHP 函数调用
想法
我以前对于 C 语言的印象是有很强的确定性,而 PHP 在执行的时候会被翻译为 C 语言执行,所以一直很好奇 PHP 怎么调用底层函数。
换句话说就是已知函数名字的情况下如何调用 C 语言中对应名字的函数?
我以前对于 C 语言的印象是有很强的确定性,而 PHP 在执行的时候会被翻译为 C 语言执行,所以一直很好奇 PHP 怎么调用底层函数。
换句话说就是已知函数名字的情况下如何调用 C 语言中对应名字的函数?
调用顺序为:
- 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
int main(int argc, char *argv[])
{
// ...
sapi_module_struct *sapi_module = &cli_sapi_module;
// ...
/* startup after we get the above ini override se we get things right */
if (sapi_module->startup(sapi_module) == FAILURE) {
// ...
}
// ...
exit_status = do_cli(argc, argv);
// ...
}
main/SAPI.h
ext/standard/array.c
/* {{{ 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, 1) == FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}
接下来找 zend_hash_sort 。
Zend/zend_hash.h
#define zend_hash_sort(ht, compare_func, renumber) \
zend_hash_sort_ex(ht, zend_sort, compare_func, renumber)
用于排序的算法是 zend_sort 。
从数组入手。
数组相关函数是 PHP 扩展的一部分,扩展名为 standard
,执行 php -m
可以看到该扩展。
该扩展的源码在 PHP 源码包的 ext/standard
,其中数组相关函数的定义在 ext/standard/array.c
。
创建对象:
zend_objects.c
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
ZEND_API const zend_object_handlers std_object_handlers = {
0, /* offset */
zend_object_std_dtor, /* free_obj */
zend_objects_destroy_object, /* dtor_obj */
zend_objects_clone_obj, /* clone_obj */
zend_std_read_property, /* read_property */
zend_std_write_property, /* write_property */
zend_std_read_dimension, /* read_dimension */
zend_std_write_dimension, /* write_dimension */
zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */
NULL, /* get */
NULL, /* set */
zend_std_has_property, /* has_property */
zend_std_unset_property, /* unset_property */
zend_std_has_dimension, /* has_dimension */
zend_std_unset_dimension, /* unset_dimension */
zend_std_get_properties, /* get_properties */
zend_std_get_method, /* get_method */
NULL, /* call_method */
zend_std_get_constructor, /* get_constructor */
zend_std_get_class_name, /* get_class_name */
zend_std_compare_objects, /* compare_objects */
zend_std_cast_object_tostring, /* cast_object */
NULL, /* count_elements */
zend_std_get_debug_info, /* get_debug_info */
zend_std_get_closure, /* get_closure */
zend_std_get_gc, /* get_gc */
NULL, /* do_operation */
NULL, /* compare */
NULL, /* get_properties_for */
};
如: