Objective
After the extension of the PHP extension framework of the automatic generation, the overall understanding of the PHP extension framework, basically can say, how to write PHP extension and key points have a certain grasp, but the key is how to write Php_function function.
This article mainly records, PHP in the call extension when the argument, then the extension function is how to take. As your own memo.
Body
1.zend_parse_parameters
To get the arguments passed by the function, you can use the Zend_parse_parameters function, and the attentive classmate will find that the official generated default function also uses this function to receive parameters.
How does this function work?
First, you can use this book as PHP's scanf. (This function is not familiar to the conscious here)
zend_parse_parameters (int num_args tsrmls_dc, char *type_spec, & parameter 1,& parameter 2 ...);
The first parameter is the number of arguments passed to the function. The usual practice is to pass it Zend_num_args (). (Zend_num_args () to indicate "how much" to pass in the parameter) this is a macro that represents the total number of arguments passed to the function.
The second parameter is for thread safety and always passes the TSRMLS_CC macro.
The third argument is a string that specifies the type of argument the function expects, followed by a list of variables that need to be updated with the parameter value. Since PHP is a weakly typed language, it uses loosely defined variables and dynamic type judgments, while C is strongly typed, and Zend_parse_parameters () is designed to convert different types of parameters into desired types. (A warning is issued when the actual value cannot be coerced to the desired type)
The fourth fifth until the nth parameter is the value to be passed in.
The third parameter is detailed
For the third parameter, here is a list of parameters to choose from:
type specifier |
the corresponding C type |
Description |
L |
Long |
Symbol integer |
D |
Double |
Floating point number |
S |
char *, int |
binary string, length |
B |
Zend_bool |
Logic type (1 or 0) |
R |
Zval * |
Resources (file pointers, database connections, etc.) |
A |
Zval * |
Union array |
O |
Zval * |
Any type of object |
O |
Zval * |
An object of the specified type. The class type of the target object needs to be provided |
Z |
Zval * |
Zval without any action |
We have two points to pay special attention to here.
1. There are two parameters for the C type corresponding to the string type. Yes. This means that you need to use this when using the Zend_parse_parameters () function:
Zend_parse_parameters (Zend_num_args () tsrmls_cc, "s", &name, &name_len)
One represents the string content and the other is the string length.
2. Need to know about, Zval is what?
Zval is the value container for the Zend engine. Whether this variable is Boolean, string, or any other type, its information is always contained in a zval union. Come a wave of zval structure:
typedef Union _ZVAL { long lval; Double dval; struct { char *val; int len; } STR; HashTable *ht; Zend_object_value obj;} Zval;
PS: About typedef is not explained, because I found that someone has written very well, please click on the usage summary of typedef
This side also involves an additional three usages to enhance our ability to receive parameters:
symbols |
explain |
| |
The arguments before it are all necessary, and then all are non-mandatory, that is, the default value. |
! |
If a null variable is received in a PHP language, it is directly converted to NULL in the C language instead of Zval encapsulated as a is_null type. |
/ |
If the passed variables share a zval with other variables, and are not references, then force the separation, the new Zval is_ref__gc==0, and Refcount__gc==1. |
| and "!" There will be specific examples below, about "/" although probably understand the meaning, but did not think of specific examples.
Take a wave of interaction with PHP
Normal look.
in PHP
<?phpfunction my_function ($msg) { echo "I received the parameter: {$msg}!\n";} My_function (' brown Alpaca ');
If My_function is written as a PHP extension:
Zend_function (my_function) { char *msg; int Msg_len; if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "s", &msg, &msg_len) = = FAILURE) { return_null (); } php_printf ("I received the parameters:"); Phpwrite (msg, msg_len); php_printf ("!\n");}
Two-parameter appearance
in PHP
<?phpfunction my_function ($email, $msg) { echo "I received parameters: {$email}, {$msg}!\n";} My_function (' 123456@qq.com ', ' brown Alpaca ');
If My_function is written as a PHP extension:
Zend_function (my_function) { char *email; int Email_len; char *msg; int Msg_len; if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS", &msg, &msg_len,&email, &email_len) = = FAILURE) { return_null (); } php_printf ("I received the parameters:"); Phpwrite (email, email_len); Phpwrite (msg, msg_len); php_printf ("!\n");}
Two parameters, one of which is optional and has a default value
<?phpfunction my_function ($email, $msg = ' Brown alpaca ') { echo ' I received parameters: {$email}, {$msg}!\n ";} My_function (' 123456@qq.com ');
If My_function is written as a PHP extension:
Zend_function (my_function) { char *email; int Email_len; Char *msg = "Brown Alpaca"; int msg_len = sizeof ("Brown Alpaca")-1; if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "S|s", &msg, &msg_len,&email, &email_len) = = FAILURE) { return_null (); } php_printf ("I received the parameters:"); Phpwrite (email, email_len); Phpwrite (msg, msg_len); php_printf ("!\n");}
This explains the use of the "|"
When the parameter is null, save the notation of the memory
The first to not save the wording
Zend_function (my_function) { zval *val; if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "Z", &val) = = FAILURE) { return_null ();} }
Save Memory
Zend_function (my_function) { zval *val; if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "z!", &val) = = FAILURE) { return_null ();} }
This example uses the "!", each zval, including the is_null type of zval, needs to occupy a certain amount of memory space, need the CPU compute resources to request memory for it, initialize, and release it after they have finished working. But many of the code is not aware of this. There is a lot of code that wraps a null value into the Zval is_null type, which can be optimized in extended development, and we can accept the parameter as NULL in the C language.
So it's a bad one! , the second example is more memory-saving.
2.zend_get_arguments ()
Usage
Examples are the best usage explanations, on the example:
Zend_function (my_function) { zval *email; if (Zend_get_parameters (Zend_num_args (), 1, &email) = = FAILURE) { php_error_docref (NULL tsrmls_cc, e_warning, " Need at least one parameter "); Return_null (); } // ... }
Differences and Features
1. Can be compatible with the old version of PHP, and only take zval as the carrier to receive parameters.
2. Direct acquisition, without parsing, no type conversion, all parameters in the extended implementation of the carrier need to be zval type.
3. When accepting a failure, it is not possible to throw an error on its own, nor can it easily handle parameters with default values.
4. Automatically forces all Copy-on-write-compliant zval to be separated, creating a new copy to be sent inside the function.
Comprehensive evaluation: or use zend_parse_parameters bar, this function to understand the next can, not to force.
3.ZEND_GET_PARAMETERS_EX ()
Usage
Zend_function (my_function) { zval **msg; if (ZEND_GET_PARAMETERS_EX (1, &msg) = = FAILURE) { php_error_docref (NULL tsrmls_cc, e_warning, "requires at least one parameter"); Return_null (); } // ...}
Zend_num_args () is not required as a parameter because it is added at a later stage and that parameter is no longer needed.
Differences and Features
1. This function is basically the same as zend_get_parameters ().
2. The only difference is that it does not automatically force the separation of all copy-on-write-compliant zval and will use the old zval characteristics
Comprehensive evaluation: It may be used in extreme situations, this function can be understood.
zend_get_parameter_**
This includes: ZEND_GET_PARAMETERS_ARRAY_EX () and Zend_get_parameters_array ()
Usage
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<argc; i++) { php_var_dump (args[i], 1 tsrmls_cc); } Efree (args);}
This is a bit complicated and needs to be explained:
The program obtains the number of parameters first, and then uses the Safe_emalloc function to request the corresponding size of memory to hold the parameters of these zval** types. Here, the ZEND_GET_PARAMETERS_ARRAY_EX () function is used to populate the parameters passed to the function into args.
Yes
This parameter is specifically designed to solve the same function as the var_dump in PHP, which can be used to pass parameters in an infinite way.
Differences and Features
1. The implementation of an extension function that is used to deal with infinite parameters.
The only difference between 2.zend_get_parameters_array and ZEND_GET_PARAMETERS_ARRAY_EX is that it fills the parameters of the zval* type into ARGS and requires Zend_num_args () as a parameter.
Comprehensive evaluation: It is really necessary to use this function when encountering an infinite parameter. Zend_parse_parameters really can't do it ~
Summarize
Throw away everything, and at least learn to use the Zend_parse_parameters (). Good. The extension function passes the parameters of the skill get.