Php extension and embedding-php internal variables

Source: Internet
Author: User
I have previously introduced the internal lifecycle of php and the thread security mechanism of Zend Engine. here this article mainly introduces how php internal variables are implemented. After learning about these implementation methods, it is quite helpful to write php, especially for php extension development. Php is

I have previously introduced the internal lifecycle of php and the thread security mechanism of Zend Engine. here this article mainly introduces how php internal variables are implemented.

After learning about these implementation methods, it is quite helpful to write php, especially for php extension development.


Php is a loose language. compared with C, you do not need to provide a type before using the variable. you can simply use it. To achieve this, php must do some work on the definition of data types.

Data type:

The most basic type is called zval or Zend Value, which is defined in the Zend/zend. h header file. Typedef struct _ zval_struct {
Zvalue_value value;
Zend_uint refcount;
Zend_uchar type;
Zend_uchar is_ref;
} Zval; zvalue_value is defined as follows: typedef union _ zvalue_value {
Long lval;
Double dval;
Struct {
Char * val;
Int len;
} Str;
HashTable * ht;
Zend_object_value obj;
} Zvalue_value; this is a union. There are two possibilities when union is used. One is that all variables share a piece of memory space, one is to select 1 for the n type.
Zend defines eight basic data types, which are basically seen in other languages, so only special types are described: IS_NULL: non-valueIS_BOOL: IS_LONGIS_DOUBLEIS_STRING: the allocated space must be the length + 1IS_ARRAY: The php array is actually hashtable, including label and dataIS_OBJECT: methods, access modifiers, constants with fields, and special event processor IS_RESOURCE are added to the array. for example, file handles or mysql handles are stored in zval type, in addition, zvalue_value corresponds to each other. Note that there are two types of judgment functions:
void describe_zval(zval *foo){    if (foo->type == IS_NULL) {        php_printf("The variable is NULL");    } else {        php_printf("The variable is of type %d", foo->type);    }}
And
void describe_zval(zval *foo){    if (Z_TYPE_P(foo) == IS_NULL) {        php_printf("The variable is NULL");    } else {        php_printf("The variable is of type %d",                            Z_TYPE_P(foo));    }}

In the first code, c is used, and in the second code, php is used. Note that the Zend header file provides many macros for zval processing. it is best to use them. Z_TYPE_P (foo). There are also Z_TYPE () and Z_TYPE_PP ()Corresponding to zval and zval ** php_printf () are some optimizations for SAPI and php output mechanisms based on printf.


Data value

Some macros can be used to obtain the zval values of different types: BVAL (): BooleanLVAL (): longDVAL (): double. This function is applicable to three different zval types. Z_TYPEThe type is determined. Then, use the macro extracted from the corresponding value to take the value.
void display_values(zval boolzv, zval *longpzv,               zval **doubleppzv){    if (Z_TYPE(boolzv) == IS_BOOL) {        php_printf("The value of the boolean is: %s\n",            Z_BVAL(boolzv) ? "true" : "false");    }    if (Z_TYPE_P(longpzv) == IS_LONG) {        php_printf("The value of the long is: %ld\n",            Z_LVAL_P(longpzv));    }    if (Z_TYPE_PP(doubleppzv) == IS_DOUBLE) {        php_printf("The value of the double is: %f\n",            Z_DVAL_PP(doubleppzv));    }}

String Processing is a little special: two macros are required. Z_STRVAAnd Z_STRLENRead the value and length respectively. we can see from the definition of the string type that it is composed of characters and length.
void display_string(zval *zstr){    if (Z_TYPE_P(zstr) != IS_STRING) {        php_printf("The wrong datatype was passed!\n");        return;    }    PHPWRITE(Z_STRVAL_P(zstr), Z_STRLEN_P(zstr));}

The ARRVAL series is used for array access: Z_ARRVAL (zv), Z_ARRVAL_P (pzv), Z_ARRVAL_PP (ppzv). In some versions of php source code, HASH_OF () is equivalent to Z_ARRVAL_P, but this macro is gradually used less.
For Object: OBJ_HANDLE, return Object handle identifier OBJ_HT handle table OBJCE class definition OBJPROP attribute hash table OBJ_HANDLER in OBJ_HT operation specific processing method for Resource directly use macro RESVAL

Data creation:

The malloc (sizeof (zval) that creates a variable and allocates space is not feasible in php. Should be used MAKE_STD_ZVAL (pzv ),It optimizes the space allocation and automatically initializes the refCount (indicating the number of times this variable is referenced) and is_ref (whether it is mandatory) attributes. Note that its input is a pointer.
ALLOC_INIT_ZVAL ()You can also perform initialization. The difference is that zval * is set to NULL.
There are many forms for setting different types of values. the form on the left is relatively simple, and the form on the right is expanded: ZVAL_NULL (pvz); Z_TYPE_P (pzv) = IS_NULL;
ZVAL_BOOL (pzv, B); Z_TYPE_P (pzv) = IS_BOOL;
Z_BVAL_P (pzv) = B? 1: 0;
ZVAL_TRUE (pzv); ZVAL_BOOL (pzv, 1 );
ZVAL_FALSE (pzv); ZVAL_BOOL (pzv, 0 );
ZVAL_LONG (pzv, l); Z_TYPE_P (pzv) = IS_LONG;
Z_LVAL_P (pzv) = l;
ZVAL_DOUBLE (pzv, d); Z_TYPE_P (pzv) = IS_DOUBLE;
Z_DVAL_P (pzv) = d;
For string processing, a separate parameter dup is provided. this parameter determines whether to create a copy of the string. for example, zval * pzva; ZVAL_STRING (pzval, "hello world", 1); because "hello_world" is a constant string, it is obviously inappropriate to directly perform operations on it, therefore, if dup is set to 1, a copy is automatically created for it and then assigned to pzval. this makes the entire process more concise.

ZVAL_STRINGL (pzv, str, len, dup); Z_TYPE_P (pzv) = IS_STRING;
Z_STRLEN_P (pzv) = len;
If (dup ){
Z_STRVAL_P (pzv) =
Estrndup (str, len + 1 );
} Else {
Z_STRVAL_P (pzv) = str;
}
ZVAL_STRING (pzv, str, dup); ZVAL _ STRINGL (pzv, str,
Strlen (str), dup); note that if dup is set to 1, it applies for a new space and copies the content, instead of a shaddow copy. ZVAL_RESOURCE (pzv, res); Z_TYPE_P (pzv) = IS_RESOURCE;
Z_RESVAL_P (pzv) = res;


Data storage

Data is stored in the symbol table. S Every time a new variable is created for the ymbol table, Zend stores the value in this internal array.The symbol table is created before RINIT and destroyed after RSHUTDOWN.
When a function or object method in a user space is called, a new symbol table is created, with the same life time as the function execution time. Two elements are defined in Zend/zend_gblobals.h:
struct _zend_executor_globals {    ...    HashTable symbol_table;    HashTable *active_symbol_table;    ...};

You can access the symbol table through EG (symbol_table. It feels like $ GLOBALS. Note that the macro EG (symbol_table) does not return a pointer. you must add &. The following comparison is very interesting: In PHP:
 
For this php code, C has done the following:
In C:
{Zval * fooval; MAKE_STD_ZVAL (fooval); // first allocate space, set the variable ZVAL_STRING (fooval, "bar", 1); // then assign a value and create a copy, you cannot directly operate on the regular string ZEND_SET_SYMBOL (EG (active_symbol_table), "foo", fooval); // register in the symbol table, foo is a label}
Active_symbol_table refers to the current symbol table executed by the program. after entering a function, it will have its own symbol table, which is similar to the stack space of a function in C. After exiting the function, its symbol table will be destroyed and return to the following state: EG (active_symbol_table) = & EG (symbol_table ), at this time, the function is not entered.

Data acquisition:When obtaining data, the zend_hash_find () function is usually used:

{    zval **fooval;    if (zend_hash_find(EG(active_symbol_table),                       "foo", sizeof("foo"),                       (void**)&fooval) == SUCCESS) {        php_printf("Got the value of $foo!");    } else {        php_printf("$foo is not defined.");    }}
This function first looks for the symbol table, finds the variable named "foo", and then returns it to fooval. The following two problems are explained:

Why declare a zval ** fooval and convert it to the form of (void **) through & fooval? Why use sizeof ("foo") for the first question, consider that we are looking for a zval *, so we should regard it as a whole. This method can avoid compilation alarms. The second problem is that sizeof (label) is mainly used to indicate the tail of the string constant label. here, 4 is also acceptable, but it is not universal enough.

Data conversion:This function is only available. for example, convert_to_string (zval * value) can convert zval to a string.


These are some descriptions of php internal variables. to distinguish different types, set to get variable values, and add and search for variables in the symbol table, this knowledge is essential.




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.