【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 */
};如: