gpt4 book ai didi

php - 如何使 ZEND_BEGIN_ARG_INFO_EX 控制传递给 PHP 扩展的参数数量?

转载 作者:可可西里 更新时间:2023-11-01 13:50:39 26 4
gpt4 key购买 nike

我正在使用 C 开发一个 PHP 扩展。到目前为止,我正在对从 PHP 用户空间传递给扩展函数的参数进行正确验证。

ZEND_BEGIN_ARG_INFO_EX 可用于为 Zend Engine 提供有关函数参数的信息。宏的第4个参数,命名为required_num_args,让引擎自动控制参数个数,省去了我这个麻烦。然而,我找不到让它工作的方法:引擎总是在没有任何警告的情况下运行扩展的功能,即使 PHP 脚本没有向那里传递足够的参数。

这是我对函数参数的定义:

ZEND_BEGIN_ARG_INFO_EX(test_func_swt_arginfo, 0, 0, 3)
ZEND_ARG_INFO(1, firstArg)
ZEND_ARG_ARRAY_INFO(0, secondArg, true)
ZEND_ARG_OBJ_INFO(1, thirdArg, SomeClass, false)
ZEND_END_ARG_INFO()

这是我对函数的定义,由 PHP 扩展导出:

static const zend_function_entry test_func_functions[] = {
PHP_FE(sample_with_types, test_func_swt_arginfo)
PHP_FE_END
};

这是我的功能:

PHP_FUNCTION(sample_with_types)
{
RETURN_TRUE;
}

这是我运行的 PHP 脚本:

<?php
sample_with_types();

预期结果:PHP 显示错误/警告/异常,类似“没有足够的参数传递给函数”;函数不执行。

实际结果:函数执行并返回true

如何正确配置函数参数结构,以便 Zend Engine 自动检查参数数量?还是我弄错了 ZEND_BEGIN_ARG_INFO_EX 宏中 required_num_args 参数的用途?

最佳答案

据我所知,这不是 ZEND_BEGIN_ARG_INFO_EX 的目的。

ZEND_BEGIN_ARG_INFO_EX 是 PHP 5 的新增功能,用于生成更简洁的代码,支持类型提示、按引用传递和反射。考虑以下仅返回 true 的实际函数的 arginfo 声明:

ZEND_BEGIN_ARG_INFO_EX(arginfo_test, 0, 0, 3)
ZEND_ARG_INFO(0, firstArg)
ZEND_ARG_OBJ_INFO(0, objNonNull, stdClass, 0)
ZEND_ARG_OBJ_INFO(0, obj, stdClass, 1)
ZEND_ARG_OBJ_INFO(1, objByRef, stdClass, 1)
ZEND_END_ARG_INFO()

效果如下:

sample_with_types();                          // ok
sample_with_types(1, null); // error: arg #2 should be stdClass
sample_with_types(1, new stdClass, null); // ok
sample_with_types(1, new stdClass, 1); // error: arg #3 should be stdClass
sample_with_types(1, new stdClass, null, 2); // error: arg #4 must be reference

此外,它还为您的函数提供反射功能:

$ref = new ReflectionFunction('sample_with_types');
var_dump($ref->getParameters());

...给出类似的输出:

array(4) {
[0]=>
&object(ReflectionParameter)#2 (1) {
["name"]=>
string(8) "firstArg"
}
[1]=>
&object(ReflectionParameter)#3 (1) {
["name"]=>
string(10) "objNonNull"
}
[2]=>
&object(ReflectionParameter)#4 (1) {
["name"]=>
string(3) "obj"
}
[3]=>
&object(ReflectionParameter)#5 (1) {
["name"]=>
string(8) "objByRef"
}
}

如果省略 arginfo,ReflectionFunction::getParameters() 将返回一个空数组。

required_num_args 宏参数是专门用于反射的,表示在反射函数时标记多少个参数是必需的。

如果你需要使参数成为必需的,而不仅仅是在使用反射时将它们标记为必需的,你仍然必须使用zend_parse_parameters,在大多数情况下,你仍然需要获取实际值参数:

PHP_FUNCTION(sample_with_types)
{
long arg1;
zval *arg2 = NULL, *arg3 = NULL, *arg4 = NULL;
zend_class_entry ce2, ce3, ce4;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "looo", &arg1,
&arg2, &ce2, &arg3, &ce3, &arg4, &ce4) == FAILURE)
{
return;
}

RETURN_TRUE;
}

请注意我在上面是如何使用 "looo"(通用对象类型)而不是 "lOO!O!"(具有 null 说明符的特定对象类型)。类型提示已使用 arginfo 指定,因此无需执行两次。

所以,没有 arginfo:

  • 您必须使用少量的 zend_fetch_class 调用和类条目来类型提示您的对象参数。
  • 它不会启用反射。
  • 您将无法声明通过引用传递的参数。
  • 它显然会产生不太干净的代码。

出于显而易见的原因,您需要确保您的 arginfo 声明和您的 zend_parse_parameters 调用匹配。

关于php - 如何使 ZEND_BEGIN_ARG_INFO_EX 控制传递给 PHP 扩展的参数数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14635111/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com