PHP extensions and embedding--php internal variables _php Tutorial

Source: Internet
Author: User
Before the introduction of the internal lifecycle of PHP and the thread-safety mechanism of the Zend engine, this article is mainly about how PHP's internal variables are implemented.

Knowing the methods of these implementations is quite helpful for writing PHP, especially for PHP extension development.


PHP is a loosely-typed language that does not need to give a type before using a variable, as opposed to C, and can be used directly. To achieve this, PHP must do some work on the definition of the data type.

Data type:

The most basic type is known as 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, where 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, two possibilities when using union, one is that all variables share a piece of memory space, and one is to select 1 of the type in it.
Zend defines 8 basic data types, eight of which are basically seen in other languages, so only the more specific types are explained: Is_null:non-valueis_bool:is_longis_doubleis_ STRING: The allocated space needs to be an array of length +1is_array:php, which is actually Hashtable, which includes the label and the Datais_object: Add methods, access modifiers, domain constants, and special event handlers on the basis of the array Is_ RESOURCE: For example, a handle to a file or a handle to MySQL is stored in the type of zval and has a separate correspondence with Zvalue_value note the following are the comparison of 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));}    }

The first code is written in C, and the second code is a PHP-style notation. Note that the Zend header file provides a lot of macros for zval processing, preferably with them, and here is the z_type_p (foo)。 There are also Z_type () and z_type_pp ()The corresponding Zval and zval**php_printf () are optimized for SAPI and PHP output mechanisms based on printf.


Data values

Some macros allow you to get the values of different types of Zval: BVAL (): Booleanlval (): Longdval (): Double This function is for three different zval types, respectively, using Z_typeThe type is judged. The values are then extracted using the corresponding values of the macro.
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) );    }}

Handling strings is a bit more special: two macros required Z_strvaAnd Z_strlenThe values and lengths are read separately, as can be seen from the definition of string type, which is made up of characters and lengths.
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));}

Access to the array is using the Arrval series: Z_arrval (ZV), z_arrval_p (Pzv), z_arrval_pp (Ppzv)There are some versions of PHP source hash_of () equivalent to z_arrval_p, but this macro has been gradually used less.
For Object:obj_handle return object handle identity Obj_ht handle table Objce class definition Objprop property hash Table Obj_handler operation specific processing method in OBJ_HT for resource resource directly with macro Resval

Data creation:

malloc (Zval), which wants to create a variable and allocate space, is not feasible here in PHP. should use Make_std_zval (pzv),It optimizes the allocation of space and automatically initializes the properties of the RefCount (indicating the number of times the variable is referenced) and is_ref (whether it is a forced reference). Note that its input is a pointer.
Alloc_init_zval ()It is also possible to initialize, except that the value of zval* is set to null.
There are many forms when setting different types of values, the left side is a relatively abbreviated form, and the right side is the expanded form: 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 to be special, a separate parameter DUP is provided. This parameter determines whether a copy of the string is created. For example Zval * PZVA; Zval_string (Pzval, "Hello World", 1); Since "Hello_world" is a constant string, it is obviously inappropriate to manipulate it directly, so setting the DUP to 1 will automatically create a copy of it and then assign it to Pzval. This makes the whole 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 If the DUP is set to 1, it is to apply for a new space and copy the content instead of a shaddow copy. Zval_resource (Pzv, RES); Z_type_p (PZV) = Is_resource;
Z_resval_p (PZV) = res;


Storage of data

The storage of the data is in the symbol table. s ymbol table, whenever a new variable is created, Zend saves the value into the inner array. The symbol table was created before Rinit and destroyed after Rshutdown.
When a function or object method of a user space is called, a new symbol table is created, with the same life 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;    ...};

The symbol table can be accessed by means of eg (symbol_table). It feels like $globals. Note that this macro returned by eg (symbol_table) is not a pointer and must be added &. The following comparison is very interesting: in PHP:
 
  
For this PHP code, C has done the following things:
In C:
{    zval *fooval;    Make_std_zval (Fooval); First allocate the space, set the variable    zval_string (fooval, "Bar", 1);//Then assign, create a copy, you cannot directly manipulate the constant string    Zend_set_symbol (EG (active_symbol _table), "foo", Fooval); Register in the symbol table, Foo is a label}
The so-called active_symbol_table refers to the program execution of the current symbol table, after entering a function, there will be its own corresponding symbol table, similar to the C in a function of its own stack space. And when the function is exited, its symbol table will be destroyed, this time back to the following state: EG (active_symbol_table) = = &eg (symbol_table), at this point did not enter the function.

access to data:When fetching data, it is more to use the Zend_hash_find () function:

{    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 up the symbol table, finds the variable named "foo", and returns it to the Fooval. Two questions are highlighted below:

Why declare a zval * * * fooval and then go through &fooval and convert to (void * *) Form? Why use sizeof ("foo") on the first question, consider that the goal we are looking for is a zval*, so think of it as a whole. Use this notation to avoid compiling alarms. The second problem, using sizeof (label) is primarily to represent the tail of the string constant label, where 4 is also possible, but not universal enough.

Data Conversion:Just say that there is this function, such as convert_to_string (Zval *value) can convert Zval to a string.


These are some of the examples of PHP internal variables, which are necessary in order to be able to distinguish between different types, set the value of a variable, and add and find variables in the symbol table.




http://www.bkjia.com/PHPjc/621628.html www.bkjia.com true http://www.bkjia.com/PHPjc/621628.html techarticle before the introduction of the internal lifecycle of PHP and the thread-safety mechanism of the Zend engine, this article is mainly about how PHP's internal variables are implemented. Understand these ...

  • 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.