diff --git a/internals2/funcs/index.xml b/internals2/funcs/index.xml index f08ecf1ef9..afaba2fa8b 100644 --- a/internals2/funcs/index.xml +++ b/internals2/funcs/index.xml @@ -3,12 +3,361 @@ Writing functions - PHP is also known as a Glue language, and extending it, can be easily done -with those extensions generators. When you use ext_skel and a prototype file -to generate the C function stubs, you will notice that all of the exported -functions created have a simple prototype such as the following: -PHP_FUNCTION(func_name) + One core element of an extension are functions which are exported to the + PHP userland. Even when you're planning to write object-oriented extensions + you are advised to read this chapter as most of the information is valid + for methods, too. + + + When adding a function to an extension, for instance after using the + ext_skel script to + create the raw infrastructure, you can create a function by implementing it + as a C function and then providing an entry for the extension's function + table. The function entry can contain a pointer to an argument information + structure. Providing this information ins not strictly necessary, unless + you plan to accept parameters by reference or want to return a reference, but + provides information that can be accessed via PHP's Reflection API. As you will see below the + parameters aren't passed as direct function parameters to the implementation + but passed on a stack, which is checked by the function's implementation + which can't directly serve as source for this information. + + + + Minimal PHP extension with one function + += 20010901 + STANDARD_MODULE_HEADER, +#endif + "demo", + demo_functions, + NULL, + NULL, + NULL, + NULL, + NULL, +#if ZEND_MODULE_API_NO >= 20010901 + "1.0.0", +#en + STANDARD_MODULE_PROPERTIES +} +/* }}} */ +]]> + + + + + In his example you can see the above discussed elements and the module + structure, if you don't remember his strucure go back to + . + + + + The first part of this extension is the actual implementation. As a + convention each exported function is preceded by a two line comment + describing the function's userland prototype and a short one line comment. + + + + For providing source code compatibility between different versions of PHP + the functions declaration is wrapped into the PHP_FUNCTION + macro. The compiler's preprocessor will, when using PHP 5.3 transform this + into a function like this: + + + + + + + + For preventing a naming conflict between a function exported to userland + and another C function with the same name the C symbol of the exported + function is prefixed with the prefix zif_. You can also see + that this prototype doesn't reference the argument stack. Accessing + parameters passed from PHP is described below. The following table lists + the C level parameters which are also defined in the + INTERNAL_FUNCTION_PARAMETERS macro. Mind that these parameters + might change between PHP versions and you should use the provide macros. + + + + INTERNAL_FUNCTION_PARAMETERS + + + + Name and type + Description + Access macros + + + + + + int ht + Number of actual parameters passed by user + ZEND_NUM_ARGS() + + + + zval *return_value + + Pointer to a PHP variable that can be filled with the return value + passed to the user. The default type is IS_NULL. + + RETVAL_*, RETURN_* + + + + zval **return_value_ptr + When returning data by reference to PHP set this to a pointer to + your variable. It is not suggested to returning by reference. + + + + + zval *this_ptr + + In case this is a method call this points to the PHP variable + holding the $this object. + + getThis() + + + + int return_value_used + + Flag indicating whether the returned value will be used by the + caller. + + + + + + +
+ + + As said the function shown above will simply return NULL to the user and do + nothing else. The function can be called, from the PHP userland, with an + arbitrary number of parameters. A more useful function consists of four + parts in general: + + + + + + Declaration of local variables. In C we have to declare locale vars, so + we do this at the functions top. + + + + + Parameter parsing. PHP passes parameters on a special stack, we have to + read them from there, verify the types, cast them if needed and bail out + in case something goes wrong. + + + + + Actual logic. Do whatever is needed. + + + + + Set the return value, cleanup, return. + + + + + + In some cases the exact order of these steps may change. Especially the + last two steps are often mixed up, but it's a good idea to stay in that + order. + + + + A simple function + + + + + + + The function above shows these parts. Let's start the analysis with the + last lines: php_printf is - as one can guess easily - PHP's + version of standard C's printf. Unlike printf it + doesn't print to the process's STDOUT channel but to the + current output stream, which might be buffered by the user. It should be + noted that php_printf, unlike most parts of PHP's API is not + binary safe, so if name contains a NULL-byte the rest would be + ignored. For a binary safe output PHPWRITE should be used. + + + + + In general it is considered to directly print data to the output stream, + it is suggested to return data as string to the user instead so the user + can decide what to do. Exceptions to this rule might be functions dealing + with binary data like images while your API should provide a way to access + the data even there. + + + + + The RETURN_TRUE macro in the last line does three things: It + sets the type of the variable we got as return_value pointer to + IS_BOOLEAN and the value to a true value. Then it + returns from the C function. So when using this macro you're housekeeping + for memory and other resources has to be completed as further code of + this function won't be executed. + + + + The zend_parse_parameters() function is responsible for reading + the parameters passed by the user from the argument stack and putting it + with proper casting in local C variables. If the user doesn't pass the wrong + number of parameters or types that can't be casted the function will emit a + verbose error and return FAILURE. In that case we simply return + from the function - by not changing the return_value the + default return value of NULL will be returned to the user. + + + + + Please mind that FAILURE is represented by a -1 + and SUCCESS by 0. To make the could clear you + should always use the named constants for comparing the value. + + + + + The first parameter to zend_parse_parameters() is the number of + parameters that have actually been passed to the function by the user. The + number is passed as ht parameter to our function but, as + discussed above, this should be considered as an implementation detail and + ZEND_NUM_ARGS() should be used. + + + + For compatibility with PHP's thread-isolation, the thread-safe resource + manager, we also have to pass the thread context using + TSRMLS_CC. Unlike in other functions this can't be the last + parameter as zend_parse_parameters expects a variable number of + parameters - depending on the number of user-parameters to read. + + + + Following the thread context the expected parameters are declared. Each + parameter is represented by a character in the string describing the type. + In our case we expect one parameter as a string so our type specification + is simply "s". + + + + Lastly one has to pass one or more pointers to C variables which should be + filled with the variable's value or provide more details. In the case of a + string we get the actual string, which will always be NULL-terminated, as a + char* and its length, excluding the NULL-byte, as + int. + + + + A documentation of all type specifiers and the corresponding additional C + types can be found in the file README.PARAMETER_PARSING_API + which is part of the source distribution. The most important types can be + found in the table below. + + + + zend_parse_parameters() type specifiers + + + + Modifier + Additional parameter types + Description + + + + + + b + zend_bool + Boolean value + + + + l + long + A integer (long) value + + + + d + double + A float (double) value + + + + s + char*, int + A binary safe string + + + + h + HashTable* + An array's hash table + + + +
+