PHP7 parameters, arrays, and zvals

Source: Internet
Author: User
Tags zend

Start

It is already possible to declare a simple function that returns a static or dynamic value. Define the INI option, declaring an internal numeric value or a global value. This section describes how to receive values for incoming parameters from the calling script (php file), and how the PHP kernel and Zend engine operate internal variables.

Receive parameters

Unlike the code of the user control, the parameters of the intrinsic function are not actually declared at the head of the function, and the function declarations are in the form of Php_function (Func_name), where the parameter declarations are not. The arguments are passed in through the address of the parameter list and are passed in to each function, regardless of whether there are arguments.

By defining the function hello_str (), it takes a parameter and then outputs it with the text of the greeting.

Php_function (hello_greetme) {    char *name = NULL;    size_t Name_len;    Zend_string *STRG;    if (Zend_parse_parameters (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 the same. Zend_num_args () tells the ZEND engine what parameters to take, TSRMLS_CC is used to ensure thread safety, and the return value detection is success or failure. Typically, the return is success. Zend automatically outputs an error message and returns control to the calling script unless the parameter passed in is too small or too many or the parameter cannot be converted to the appropriate type.

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

In addition, there is an int variable passed to zend_parse_parameters () by address. This enables the Zend engine to provide the byte length of the string, so that binary security functions no longer rely on strlen (name) to determine the length of the string. Because you actually use STRLEN (name) to not even get the correct result, name may contain a null character before the end of the string.

In PHP7, providing another way to get parameters fast_zpp is to improve the performance of parameter parsing.

#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 the actual use of PHP, the Zval data type stores all the user-space variables. Three kinds of "complex" data types: resources, arrays, objects. When their data type codes are used for zend_parse_parameters (), the Zend engine performs type checking, but because there are no data types corresponding to them in C, type conversions are not performed.

Zval

Generally speaking, zval and PHP user space variables are very difficult to understand. To PHP7, its structure is defined in the 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 R        eserved)/* 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;};

As you can see, the variables are stored through the _ZVAL_STRUCT structure, and the values of the variables are of type zend_value:

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 structure looks very large, but a closer look, in fact, is a consortium, the expansion of value, U1 is Type_info,u2 is a variety of other auxiliary fields.

Zval type

The data stored by a variable is of a data type, and PHP7 has the following types in general, as 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 I S_object 8#define is_resource 9#define is_reference 10/* Constant Express                    Ions */#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 

Test

Write a hello_typeof () that resembles GetType () to obtain the type of the variable:

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"); }}

There is not much difference between using retval_string () and the previous return_string (), which are macros. Except that the return_string contains the Retval_string macro instead, which is defined in detail in zend/zend_api.h:

#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 previously used Zval is allocated by the Zend Engine and is 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

Arrays as variables that carry other variables. A well-known HashTable is used in the internal implementation. The simplest way to create an array that will be returned pphp:

To do a test:

Php_function (Hello_get_arr) {    array_init (return_value);    Add_next_index_null (return_value);    Add_next_index_long (return_value);    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 was changed from four to three.

Array traversal

Let's say we need an extension that replaces the following features:

<?phpfunction hello_array_strings ($arr) {    if (!is_array ($arr)) {        return NULL;    }    printf ("The array passed contains%d elements\n", COUNT ($arr));    foreach ($arr as $data) {        if (is_string ($data))            echo $data. ' \ n ';    }}

PHP7 's traversal array and php5 are much worse, and 7 provides some specialized macros to traverse the element (or keys). The first parameter of a macro is hashtable, and the other variables are assigned 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)

So its corresponding function is implemented 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 the new traversal method, and I look at the PHP5 processing, debugging the above code took a lot of effort, in general, the way to traverse the macro greatly reduced the coding volume. A hash table is an important part of PHP, and it's time to look into it.

  • Related Article

    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.