Parameters for writing PHP extension functions

Source: Internet
Author: User
Tags php language
Parameters of the function
The simplest way to get the arguments passed by the function caller is to use the Zend_parse_parameters () function. The first few parameters of the zend_parse_parameters () function can be generated directly from the kernel macro, in the form: Zend_num_args () TSRMLS_CC, note that there is a space between the two, but there is no comma. As can be seen from the name, Zend_num_args () represents the number of parameters. The argument that needs to be passed to the Zend_parse_parameters () function is a string for formatting, just like the first parameter of printf. The following are some of the most commonly used symbols.
Type_spec is a formatted string, and its common meanings are as follows:
The type that the parameter represents
b Boolean
L Integer Integer type
D Floating point Float type
S string strings
R Resource Resources
A array of arrays
O Object instance
O object instance of a specified type specific types of objects
Z non-specific zval any type ~
Z zval** Type
F means the function, the method name, the PHP5.1 Wood has ...
This function is like the printf () function, and the following arguments correspond to the format one by one in the formatted string. Some of the underlying types of data are mapped directly to the types in the C language.
Zend_function (Sample_getlong) {

Long Foo;
if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "L", &foo) = = FAILURE)
{
Return_null ();
}
php_printf ("The integer value of the parameter is:%ld\n", foo);
Return_true;
}
In general, the data of the two data types, int and long, are often the same, but there are exceptions. So we should not change the array of long into an int, especially in a 64-bit platform, which will cause some bugs that are not easy to troubleshoot. So when we receive parameters through the Zend_parse_parameter () function, we should use those types of variables that the kernel has agreed upon as vectors.
parameter corresponds to the data type in C
b Zend_bool
L Long
D Double
s char*, int the former receives the pointer, the latter receives the length
R zval*
A zval*
o zval*
O zval*, zend_class_entry*
Z zval*
Z zval**
Note that all of the compound type parameters in the PHP language require the zval* type as a vector because they are some of the data structures that the kernel customizes. We must make sure that the parameters and vectors are of the same type and, if necessary, can be converted into types, such as converting an array to a Stdclass object. S and O (letter capital Euro) types need to be said separately, as they all require two vectors. We will look at the specific implementations of the objects in PHP in the following chapters. So let's rewrite one of the functions we defined in Chapter Fifth:
function Sample_hello_world ($name) {
echo "Hello $name!\n";
}
When writing an extension, we need to use Zend_parse_parameters () to receive the string:
Zend_function (Sample_hello_world) {
Char *name;
int Name_len;

if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "s", &name, &name_len) = = FAILURE)
{
Return_null ();
}
php_printf ("Hello");
Phpwrite (name, Name_len);
php_printf ("!\n");
}
If the number of arguments passed to the function is less than zend_parse_parameters () the number of arguments to receive, it fails and returns failure.
If we need to receive multiple parameters, we can list the receiving vector directly in the parameters of Zend_parse_paramenters (), such as:
function Sample_hello_world ($name, $greeting) {
echo "Hello $greeting $name!\n";
}
Sample_hello_world (' John Smith ', ' Mr. ');
This should be done in the PHP extension:
Zend_function (Sample_hello_world) {
Char *name;
int Name_len;
Char *greeting;
int Greeting_len;
if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS", &name, &name_len, &greeting, &greeting_len ) = = FAILURE) {
Return_null ();
}
php_printf ("Hello");
Phpwrite (greeting, Greeting_len);
php_printf ("");
Phpwrite (name, Name_len);
php_printf ("!\n");
}
In addition to the parameters defined above, there are three additional parameters to enhance our ability to receive parameters, as follows:
Type Modifier Meaning
| 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.
Default values for function parameters
Now let's go ahead and rewrite Sample_hello_world (), and then we'll use the default values for some parameters in the PHP language like this:
function Sample_hello_world ($name, $greeting = ' mr./ms. ') {
echo "Hello $greeting $name!\n";
}
Sample_hello_world (' Ginger Rogers ', ' Ms. ');
Sample_hello_world (' Fred Astaire ');
At this point, you can pass only one parameter to the Sample_hello_world, or you can pass the full two parameters. So how do we do that in an extended function? We need to use the Zend_parse_parameters (|) parameter, the parameter before this parameter is considered to be necessary, after that it is considered to be non-necessary, if not passed, will not modify the vector.
Zend_function (Sample_hello_world) {
Char *name;
int Name_len;
Char *greeting = "Mr./mrs.";
int greeting_len = sizeof ("Mr./mrs.")-1;


if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "S|s",
&name, &name_len, &greeting, &greeting_len) = = FAILURE) {
Return_null ();
}
php_printf ("Hello");
Phpwrite (greeting, Greeting_len);
php_printf ("");
Phpwrite (name, Name_len);
php_printf ("!\n");
}
If you do not pass the second argument, the extension function is considered default and does not modify the vector. So, we need to pre-set the value of the carrier, which is often null, or a value related to the logic of the function. Each zval, including the is_null type of Zval, takes up a certain amount of memory space and requires CPU compute resources to request memory, initialize, and release it after they have completed their work. 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 take the parameter to NULL in the city C language. Let's look at the following code for this question:
Zend_function (sample_arg_fullnull) {
Zval *val;
if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "Z", &val) = = FAILURE) {
Return_null ();
}
if (Z_type_p (val) = = Is_null) {
val = Php_sample_make_defaultval (Tsrmls_c);
}
...
}
Zend_function (Sample_arg_nullok) {
Zval *val;
if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "z!",
&val) = = FAILURE) {
Return_null ();
}
if (!val) {
val = Php_sample_make_defaultval (Tsrmls_c);
}
}
These two pieces of code don't seem very different at first, but the first piece of code does require more CPU and memory resources. Perhaps this technique in peacetime does not have much use, but the skill is not pressure body, know is better than don't know.

Forced separation
When a variable is passed to a function, whether it is referenced or not, its REFCOUNG__GC property will be added one, at least 2. One is itself, and the other is copy passed to the function. Before changing this zval, it is sometimes necessary to divide it into two copies of the actual meaning in advance. This is the function of the "/" format character. It will split the copy-on-write zval into two completely separate copies in advance so that we can manipulate it arbitrarily in the code below. Otherwise we may need to keep reminding ourselves of the separation of the received parameters. Like the NULL flag, this modifier goes after the type it means to impact. Also like the NULL flag, you won ' t know you need this feature until you actually has a use for it.

Zend_get_arguments ()
If you want your extension to be compatible with older versions of PHP, or if you only want to take zval as a vector to receive parameters, you might consider using the zend_get_parameters () function to receive parameters. Zend_get_parameters () is different from zend_parse_parameters (), we can see from the name that it gets directly without parsing. First of all, it does not automatically type conversion, all parameters in the extension implementation of the vector need to be zval type, let us look at a simple example:
Zend_function (Sample_onearg) {
Zval *firstarg;
if (Zend_get_parameters (Zend_num_args (), 1, &firstarg) = = FAILURE) {
Php_error_docref (NULL tsrmls_cc, e_warning, "expected at least 1 parameter.");
Return_null ();
}
/* Do something with firstarg ... */
}
Second, zend_get_parameters () does not throw an error on its own when receiving a failure, nor can it easily handle parameters with default values. The last point, unlike Zend_parse_parameters, is that it automatically forces the separation of all copy-on-write-compliant zval, creating a new copy to be sent inside the function. If you want to use other features but you don't need it, try using the ZEND_GET_PARAMETERS_EX () function to receive the parameters. In order to not detach the Copy-on-write variable, the ZEND_GET_PARAMETERS_EX () parameter is of type zval**, not zval*. This function is less often used, and may only be thought of when you encounter some extreme problems, but it is simple to use:
Zend_function (Sample_onearg) {
Zval **firstarg;
if (ZEND_GET_PARAMETERS_EX (1, &firstarg) = = FAILURE) {
Wrong_param_count;
}
/* Do something with firstarg ... */
}
Note that ZEND_GET_PARAMETERS_EX does not require Zend_num_args () as a parameter because it is added later, and that parameter is no longer needed.
The Wrong_param_count macro is also used in the above example, and its function is to throw an e_warning level error message and return it automatically.

Variable parameters
There are two other zend_get_parameter_** functions that are specifically designed to solve the problem of many parameters or the number of parameters that cannot be known in advance. Consider the use of the Var_dump () function in the PHP language, and we can pass any number of arguments to it, which is actually implemented in the kernel:
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 php_var_dump (Args[i], 1 tsrmls_cc);
}
Efree (args);
}
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. You may have immediately thought that there is a function called Zend_get_parameters_array (), except that it fills the parameters of the zval* type into ARGS and requires Zend_num_args () as a parameter.
  • 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.