How to make ZEND_BEGIN_ARG_INFO_EX control the number of arguments passed to the PHP extension?

I am developing a PHP extension using C. So far, I am working on correctly checking the arguments passed to the extension function from the PHP user space.

The macro ZEND_BEGIN_ARG_INFO_EXcan be used to provide information about function arguments to the Zend Engine. The 4th macro parameter, called required_num_args, allows the author to automatically control the number of arguments, removing this problem with me. However, I could not find a way to make it work: the engine always starts the extension function without any warnings, even if the PHP script does not pass enough arguments.

Here is my definition of function arguments:

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()

Here is my definition of the functions exported by the PHP extension:

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 script :

<?php
sample_with_types();

: PHP //, - " "; .

: true.

, Zend Engine ? required_num_args ZEND_BEGIN_ARG_INFO_EX?

+5
1

, ZEND_BEGIN_ARG_INFO_EX.

ZEND_BEGIN_ARG_INFO_EX - PHP 5, , , . arginfo , true:

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!" ( ) . hinting arginfo, .

, arginfo:

  • zend_fetch_class .
  • .
  • , .
  • , .

, arginfo zend_parse_parameters.

+8

All Articles