PHP7 parameters, arrays, and Zvals

Source: Internet
Author: User
This can already declare simple functions and return static or dynamic values. Define the INI option to declare an internal value or a global value. This section describes how to receive the value of parameters passed in from the call script (PHP file) and how to operate internal variables in the PHP kernel and Zend Engine.

Start

This can already declare simple functions and return static or dynamic values. Define the INI option to declare an internal value or a global value. This section describes how to receive the value of parameters passed in from the call script (PHP file) and how to operate internal variables in the PHP kernel and Zend Engine.

Receiving parameters

Unlike the code of the user control, the internal function parameters are not actually declared in the function header. function declarations are in the form of PHP_FUNCTION (func_name), and parameter declarations are not included. Parameters are passed in through the address of the parameter list, and each function is passed in, regardless of whether a parameter exists.

Through the definition function hello_str (), it will receive a parameter and output it together with the greeting text.

PHP_FUNCTION (hello_greetme) {char * name = NULL; size_t name_len; zend_string * strg; if (random (ZEND_NUM_ARGS () TSRMLS_CC, "s", & name, & name_len) = FAILURE) {RETURN_NULL ();} strg = strpprintf (0, "Hello: % s", name); RETURN_STR (strg );}

Most zend_parse_parameters () blocks look similar. ZEND_NUM_ARGS () informs Zend Engine of the parameter information to be retrieved. TSRMLS_CC is used to ensure thread security. the returned value is SUCCESS or FAILURE. Generally, SUCCESS is returned. Unless there are too few or too many input parameters or the parameters cannot be converted to an appropriate type, Zend automatically outputs an error message and returns the control to the calling script.

Specifying "s" indicates that this function expects only one parameter to be passed in, and the parameter is converted to the string data type. The address is used to pass in the char * variable.

In addition, an int variable is passed to zend_parse_parameters () through the address (). This enables the Zend Engine to provide the length of the string in bytes. Therefore, binary secure functions no longer rely on strlen (name) to determine the length of the string. Because the use of strlen (name) is not even correct, because name may contain NULL characters before the end of the string.

In php7, another way to obtain parameters is provided, FAST_ZPP, to improve the performance of parameter resolution.

#ifdef FAST_ZPPZEND_PARSE_PARAMETERS_START(1, 2)    Z_PARAM_STR(type)    Z_PARAM_OPTIONAL    Z_PARAM_ZVAL_EX(value, 0, 1)    ZEND_PARSE_PARAMETERS_END();#endif

Parameter type table

The last four types are zvals *. this is because in actual use of php, the zval data type stores all user space variables. Three "complex" data types: Resource, array, and object. When their data type code is used for zend_parse_parameters (), the Zend Engine performs a type check, but the type conversion is not performed because there is no data type corresponding to them in C.

Zval

In general, zval and php user space variables are difficult to understand. In PHP7, its structure is defined in Zend/zend_types.h:

struct _zval_struct {    zend_value        value;            /* value */    union {        struct {            ZEND_ENDIAN_LOHI_4(                zend_uchar    type,         /* active type */                zend_uchar    type_flags,                zend_uchar    const_flags,                zend_uchar    reserved)     /* call info for EX(This) */        } v;        uint32_t type_info;    } u1;    union {        uint32_t     next;                 /* hash collision chain */        uint32_t     cache_slot;           /* literal cache slot */        uint32_t     lineno;               /* line number (for ast nodes) */        uint32_t     num_args;             /* arguments number for EX(This) */        uint32_t     fe_pos;               /* foreach position */        uint32_t     fe_iter_idx;          /* foreach iterator index */        uint32_t     access_flags;         /* class constant access flags */        uint32_t     property_guard;       /* single property guard */    } u2;};

We can see that the variable is stored through the _ zval_struct struct, and the variable value is of the zend_value type:

typedef union _zend_value {    zend_long         lval;             /* long value */    double            dval;             /* double value */    zend_refcounted  *counted;    zend_string      *str;    zend_array       *arr;    zend_object      *obj;    zend_resource    *res;    zend_reference   *ref;    zend_ast_ref     *ast;    zval             *zv;    void             *ptr;    zend_class_entry *ce;    zend_function    *func;    struct {        uint32_t w1;        uint32_t w2;    } ww;} zend_value;

Although the struct looks very large, it is actually a consortium. The value is expanded. u1 is type_info and u2 is a variety of other auxiliary fields.

Zval type

The data stored in the variable is of the data type. in php7, the following types are available, which are defined in Zend/zend_types.h:

/* regular data types */#define IS_UNDEF                    0#define IS_NULL                     1#define IS_FALSE                    2#define IS_TRUE                     3#define IS_LONG                     4#define IS_DOUBLE                   5#define IS_STRING                   6#define IS_ARRAY                    7#define IS_OBJECT                   8#define IS_RESOURCE                 9#define IS_REFERENCE                10/* constant expressions */#define IS_CONSTANT                 11#define IS_CONSTANT_AST             12/* fake types */#define _IS_BOOL                    13#define IS_CALLABLE                 14#define IS_ITERABLE                 19#define IS_VOID                     18/* internal types */#define IS_INDIRECT                 15#define IS_PTR                      17#define _IS_ERROR                   20

Test

Write a hello_typeof () similar to gettype () to get the variable type ():

PHP_FUNCTION(hello_typeof){    zval *userval = NULL;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &userval) == FAILURE) {        RETURN_NULL();    }    switch (Z_TYPE_P(userval)) {        case IS_NULL:            RETVAL_STRING("NULL");            break;        case IS_TRUE:            RETVAL_STRING("true");            break;        case IS_FALSE:            RETVAL_STRING("false");            break;        case IS_LONG:            RETVAL_STRING("integer");            break;        case IS_DOUBLE:            RETVAL_STRING("double");            break;        case IS_STRING:            RETVAL_STRING("string");            break;        case IS_ARRAY:            RETVAL_STRING("array");            break;        case IS_OBJECT:            RETVAL_STRING("object");            break;        case IS_RESOURCE:            RETVAL_STRING("resource");            break;        default:            RETVAL_STRING("unknown type");    }}

Here, RETVAL_STRING () is not much different from the previous RETURN_STRING (). They are all macros. Only RETURN_STRING contains the macro replacement of RETVAL_STRING, which is defined in Zend/zend_API.h in detail:

#define RETVAL_STRING(s)                ZVAL_STRING(return_value, s)#define RETVAL_STRINGL(s, l)            ZVAL_STRINGL(return_value, s, l)#define RETURN_STRING(s)                { RETVAL_STRING(s); return; }#define RETURN_STRINGL(s, l)            { RETVAL_STRINGL(s, l); return; }

Create zval

The zval used previously is allocated space by the Zend Engine and released in the same way. However, sometimes you need to create your own zval. you can refer to the following code:

{    zval temp;    ZVAL_LONG(&temp, 1234);}

Array

Array is used as a variable to carry other variables. The well-known HashTable is used in internal implementation. to create an array that will be returned to PPHP, the simplest method is as follows:

Perform a test:

PHP_FUNCTION(hello_get_arr){    array_init(return_value);    add_next_index_null(return_value);    add_next_index_long(return_value, 42);    add_next_index_bool(return_value, 1);    add_next_index_double(return_value, 3.14);    add_next_index_string(return_value, "foo");    add_assoc_string(return_value, "mno", "baz");    add_assoc_bool(return_value, "ghi", 1);}

The add _ * _ string () function parameter is changed from four to three.

Array traversal

Suppose we need an extension that replaces the following features:

 

PHP 7's traversal array is much different from php5, and 7 provides some specialized macros to traverse elements (or keys ). The first parameter of the macro is HashTable. other variables are allocated to each iteration:

ZEND_HASH_FOREACH_VAL (ht, val)
ZEND_HASH_FOREACH_KEY (ht, h, key)
ZEND_HASH_FOREACH_PTR (ht, ptr)
ZEND_HASH_FOREACH_NUM_KEY (ht, h)
ZEND_HASH_FOREACH_STR_KEY (ht, key)
ZEND_HASH_FOREACH_STR_KEY_VAL (ht, key, val)
ZEND_HASH_FOREACH_KEY_VAL (ht, h, key, val)

Therefore, its function implementation is as follows:

PHP_FUNCTION(hello_array_strings){    ulong num_key;    zend_string *key;    zval *val, *arr;    HashTable *arr_hash;    int array_count;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {        RETURN_NULL();    }    arr_hash = Z_ARRVAL_P(arr);    array_count = zend_hash_num_elements(arr_hash);    php_printf("The array passed contains %d elements\n", array_count);    ZEND_HASH_FOREACH_KEY_VAL(arr_hash, num_key, key, val) {        //if (key) { //HASH_KEY_IS_STRING        //}        PHPWRITE(Z_STRVAL_P(val), Z_STRLEN_P(val));        php_printf("\n");    }ZEND_HASH_FOREACH_END();}

Because this is a new traversal method, but I still look at the PHP 5 processing method. it took a lot of effort to debug the above code. In general, the macro traversal method greatly reduces the encoding volume. Hash table is an important part of php. you have time to study it.

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.