Php extension and embedding-php Extension Parameters

Source: Internet
Author: User
In previous articles, functions are relatively simple in receiving parameters and return types, but they are often more complex in practice. This article mainly describes how to receive parameters from the user space in php extension development, and how to specify the type and number of parameters.

In previous articles, functions are relatively simple in receiving parameters and return types, but they are often more complex in practice. This article mainly describes how to receive parameters from the user space in php extension development and check the type and number of parameters.


1. use zend_parse_parameters () for automatic type conversion

In php extensions, the easiest way to get input parameters is to use the zend_parse_parameters () function.

The first parameter called for this function is always ZEND_NUM_ARGS () TSRMLS_CC. this parameter returns the number of input parameters of the int type.
The second parameter is the format parameter, which is composed of string types, corresponding to different types supported by Zend Engine.
Given the possible types of the format parameter:
The following parameters depend on the type of the previous request. For a simple type, this parameter is generally a reference primitive, as shown in the following example:
PHP_FUNCTION(sample_getlong){    long foo;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,                         "l", &foo) == FAILURE) {        RETURN_NULL();    }    php_printf("The integer value of the parameter you "             "passed is: %ld\n", foo);    RETURN_TRUE;}
Here is l, which is the long type. Therefore, a long foo parameter is declared in advance, and the value is passed in through reference. The following gives a more detailed relationship between the parameters and the types in C: B ------ zend_booll ------- longd ------- doubles ------- char *, intr ------- zval * a ------ zval * o ------ zval * O ----- zval *, zend_class_entry * z ------ zval * Z ----- zval **
Note that the complex types use the simple zval * type. This is the same as returning a complex type without RETURN. What ZPP does is to ensure that the received zval * is of the correct type. If necessary, it also performs implicit conversion, for example, converting an array into a stdClass object.
For the s type, it is special. a char * is an int. this is mainly because of the special structure of the strings in php:
function sample_hello_world($name) {    echo "Hello $name!\n";}
In C, the zend_parse_parameters function is used:
PHP_FUNCTION(sample_hello_world){    char *name;    int name_len;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",                        &name, &name_len) == FAILURE) {        RETURN_NULL();    }    php_printf("Hello ");    PHPWRITE(name, name_len);    php_printf("!\n");}

If multiple parameters exist, zend_parse_parameters extracts these parameters from left to right:
function sample_hello_world($name, $greeting) {    echo "Hello $greeting $name!\n";}sample_hello_world('John Smith', 'Mr.');
Or:
PHP_FUNCTION(sample_hello_world){    char *name;    int name_len;    char *greeting;    int greeting_len;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",      &name, &name_len, &greeting, &greeting_len) == FAILURE) {        RETURN_NULL();    }    php_printf("Hello ");    PHPWRITE(greeting, greeting_len);    php_printf(" ");    PHPWRITE(name, name_len);    php_printf("!\n");}

In addition to the type identifier, there are three metacharacters to modify the parameter processing method: |: If you see it, it indicates that the preceding parameters are required, and the following parameters are optional! : If a null variable in the php language is received, it is directly converted to NULL in the C language, instead of zval encapsulated into IS_NULL.
/: If the passed variable shares a zval with other variables and is not a real reference, force separation is required. the is_ref _ gc = 0 and refcount _ gc = 1 of the new zval Optional parameters:You can provide default values for parameters in php:
function sample_hello_world($name, $greeting='Mr./Ms.') {    echo "Hello $greeting $name!\n";}
In this case, the second parameter is not provided:
sample_hello_world('Ginger Rogers','Ms.');sample_hello_world('Fred Astaire');

In the interpretation of C, there are similar implementation methods:
PHP_FUNCTION (sample_hello_world) {char * name; int name_len; char * greeting = "Mr. /Mrs. "; int greeting_len = sizeof (" Mr. /Mrs. ")-1; // specify the default value and find the default length if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC," s | s ", & name, & name_len, & greeting, & greeting_len) = FAILURE) {// special metacharacters | use RETURN_NULL ();} php_printf ("Hello"); PHPWRITE (greeting, greeting_len) immediately ); php_printf (""); PHPWRITE (name, name_len); php_p Rintf ("! \ N ");}

For optional parameters, unless specified, there is usually no value, so it is important to provide default parameters. In most cases, it is NULL/0.


IS_NULL vs null:
Every zval type, even the simplest IS_NULL type, occupies a certain amount of memory space, and it also takes time to apply for and release them. Therefore, this type is not necessary in many cases. the following two sections of code provide a comparison:

PHP_FUNCTION (sample_arg_fullnull) {zval * val; if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "z", & val) = FAILURE) {RETURN_NULL ();} if (Z_TYPE_P (val) = IS_NULL) {// use the zval check to empty mode val = php_sample_make_defaultval (TSRMLS_C );}... PHP_FUNCTION (sample_arg_nullok) {zval * val; if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "z! ", & Val) = FAILURE) {RETURN_NULL ();} if (! Val) {// The method for checking the C language style. val = php_sample_make_defaultval (TSRMLS_C );}...

Forced Seperation Forced separation:

When a variable is passed into a function, no matter whether it is referenced or not, refcount is always at least 2. one is itself, and the other is a copy of the function. Before changing this zval, it is necessary to separate it from a non-referenced set.
It is very convenient to use/. it automatically isolates any variables referenced by copy-on-write (that is, false references.
This feature is the same as the NULL flag and can be used only when necessary.


Zend_get_parameters ():
If you want to be compatible with older versions of php or just want to use zval as the carrier to receive parameters, you can use the zend_get_parameters () function to receive parameters.
Compared with zend_parse_parameters (), it is obtained directly without parsing. No automatic type conversion will be performed. all parameters are implemented using zval.

ZEND_FUNCTION(sample_onearg) {
      zval *firstarg;    if (zend_get_parameters(ZEND_NUM_ARGS(), 1, &firstarg)== FAILURE) {        php_error_docref(NULL TSRMLS_CC, E_WARNING,"Expected at least 1 parameter.");        RETURN_NULL();    }    /* Do something with firstarg... */}

At the same time, it does not throw an error when receiving failed messages, nor can it process parameters with default values, the last difference from parse is that it automatically separates all zval conforming to copy-on-write and generates a brand new copy to the function.
If you do not need this function, you can use zend_get_parameters_ex (). its parameter is zval **.

ZEND_FUNCTION (sample_onearg) {zval ** firstarg; if (zend_get_parameters_ex (1, & firstarg) = FAILURE) {WRONG_PARAM_COUNT; throws an E_WARNING error message and returns it automatically. }/*



Variable parameters:

There are also two types of zend_get_parameters _ ** functions, which are used to solve many or fail to know the number of parameters in advance. The var_dump () function in php can input any number of parameters.

ZEND_FUNCTION (var_dump) {int I, argc = ZEND_NUM_ARGS (); zval *** args; args = (zval ***) safe_emalloc (argc, sizeof (zval **), 0); if (ZEND_NUM_ARGS () = 0 | zend_get_parameters_array_ex (argc, args) = FAILURE) {efree (args); WRONG_PARAM_COUNT;} for (I = 0; I
The program first obtains the number of parameters, and then uses the safe_emalloc function to apply for memory of the corresponding size to store these zval ** parameters. Here, the zend_get_parameters_array_ex () function is used to fill in the parameters passed to the function into args. A zend_get_parameters_array () function also exists. The only difference is that it fills the zval * type parameters in args, and ZEND_NUM_ARGS () is required as the parameter.



2. Arg info parameter and type binding

The arg info structure is only available in ZE2. Each arg info declaration is composed of a ZEND_BEGIN_ARG_INFO () or ZEND_BEGIN_ARG_INFO_EX () macro, followed by 0 or multiple ZEND_ARG _ * INFO (), and ended with ZEND_END_ARG_INFO.
Suppose you want to rewrite the count () function:

PHP_FUNCTION(sample_count_array){    zval *arr;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a",                                    &arr) == FAILURE) {        RETURN_NULL();    }    RETURN_LONG(zend_hash_num_elements(Z_ARRVAL_P(arr)));}

Zend_parse_parameters () ensures that the input parameters in your function are an array. However, if you need to use zend_get_parameter (), you need to perform built-in type checks in the function. Unless the type is bound:

ZEND_BEGIN_ARG_INFO(php_sample_array_arginfo, 0)         ZEND_ARG_ARRAY_INFO(0, "arr", 0)     ZEND_END_ARG_INFO()。。。     PHP_FE(sample_count_array, php_sample_array_arginfo)  。。。

In this way, zend engine will check the type for you. At the same time, a parameter name is also given to make the generated error information more readable.

For objects, you can also use arg info to limit them:

ZEND_BEGIN_ARG_INFO(php_sample_class_arginfo, 0)         ZEND_ARG_OBJECT_INFO(1, "obj", "stdClass", 0)     ZEND_END_ARG_INFO()

Here, the first parameter is set to 1, indicating that the object is passed by reference in ZE2. Do not forget the allow_null option of array and object.
If php4 is used, you can only use PHP_TYPE_P () for check, or use convert_to_type () for type conversion.









Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.