Http://devzone.zend.com/public/view/tag/ExtensionPart I: Introduction to PHP and Zend writing extensions I-PHP and Zend starting http://devzone.zend.com/article/1021-Extension-Writing-Part-I-Introduction-to-PHP-and-ZendPart II: Parameters, Arrays, and ZVALs writing extensions _ II-Parameters, Arrays and ZVALshttp: // Parameters II: Parameters, Arrays, and ZVALs [continued] write extended _ II-Parameters, Arrays, and ZVALs [continue] http://devzone.zend.com/article/1023-Extension-Writing-Part-II-Parameters-Arrays-and-ZVALs-continuedPart III: Resources write extended _ III-resource http://devzone.zend.com/article/1024-Extension-Writing-Part-III-Resources
Compile extension I: PHP and Zend start Extension tutorial by Sara Golemon | Monday, February 28,200 5
What is an extension? Life cycle memory allocation build Build Environment Hello World build your expansion initial settings (INI) global numerical initial settings (INI) as global numerical verification (CODE) Integrity what is the next step?
Now that you are reading this tutorial, you may be interested in programming PHP extensions. If you don't know this interest, you will find it at the end. This tutorial assumes that you are familiar with the language used for PHP and Its Interpreter implementation: C. Let's start by specifying why you want to write PHP extensions. Restricted by the abstraction of the PHP language itself, PHP cannot directly access certain libraries or operating system-specific calls. You want to customize PHP behavior in some unusual ways. You have some ready-made PHP code, but you know it can (run) Faster, (occupy space) smaller, and consume less memory. You have some good code for sale and the buyer can use it, but the important thing is that you cannot see the source code. These are all very legitimate reasons. However, before creating an extension, you must first understand what the extension is? What is an extension? If you have used PHP, you must have used extensions. Except for a few, functions in each user space are organized in different extensions. Many of these functions are enough to be standard extensions-the total number exceeds 400. PHP itself has 86 extensions (the time when the original article was written), and each of them contains about 30 functions on average. There are about 2500 functions in mathematical operations. It seems that this is not enough. The PECL repository provides more than 100 extensions, and more can be found on the Internet. "In addition to the extended functions, what else does it have ?" I heard your question. "What is the extension? What is the 'core' of PHP ?" The core of PHP is composed of two parts. The bottom layer is the Zend engine (ZE ). ZE parses human readable scripts into machine-readable symbols and then executes these symbols in the process space. ZE also handles memory management, variable scopes, and scheduling program calls. The other part is the PHP kernel, which is bound to the SAPI layer (Server Application Programming Interface, usually involves host environments, such as Apache, IIS, CLI, CGI, etc.) and processes communications with it. It also provides a consistent control layer for the detection of safe_mode and open_basedir, just as the stream layer uses fopen (), fread (), and fwrite () and other user space functions are connected with files and network I/O. Lifecycle when a given SAPI is started, for example, in the response to/usr/local/apache/bin/apachectl start, PHP starts by initializing its kernel subsystem. At the end of the startup routine, it loads the code for each extension and calls its module initialization routine (MINIT ). This allows each extension to initialize internal variables, allocate resources, register resource processors, and register its own functions with ZE, so that the script can know which code to execute when calling the functions. Next, PHP waits for the page to be processed by the SAPI layer request. For sapis such as CGI or CLI, this will happen immediately and only once. For Apache, IIS, or other mature web server SAPI, each remote user request page will occur. Therefore, it may be repeated many times or concurrently. Regardless of how requests are generated, PHP starts to require ZE to establish the runtime environment of the script, and then calls each extended request initialization (RINIT) function. RINIT gives extensions the opportunity to set specific environment variables, allocate resources based on requests, or execute other tasks, such as review. The session extension contains a typical example of RINIT. If the session. auto_start option is enabled, RINIT will automatically trigger the session_start () function of the user space and pre-assemble the $ _ SESSION variable. Once the request is initialized, ZE starts to take over the control, translates the PHP script into a symbol, and finally forms an operation code and runs it gradually. If any operation code needs to call an extended function, ZE binds the parameter to the function, and temporarily gives control until the function stops running. After the script is run, PHP calls the RSHUTDOWN function of each extension to execute the final cleanup (for example, saving session variables to a disk ). Next, ZE executes the cleanup process (garbage collection)-effectively executes unset () for each variable used during the previous request (). Once completed, PHP continues to wait for other SAPI documentation requests or close signals. For sapis such as CGI and CLI, there is no "Next request", so SAPI is immediately closed. During the shutdown, PHP traverses each extension again, calls its module shutdown function, and finally closes its kernel subsystem. This process may sound frustrating, but once you go deep into a running extension, you will gradually begin to understand it. Memory Allocation in order to avoid memory loss due to poor write expansion, ZE uses an additional flag to execute its internal memory manager to identify durability. Persistent memory allocation means more persistent than a single request. In contrast, non-persistent allocation during the request period will be released at the end of the request, whether or not the release (memory) function is called. For example, variables in the user space are allocated as non-persistent variables because they are useless after the request ends. However, theoretically, the extension can rely on ZE to automatically release non-persistent memory at the end of the page request, but this is not recommended. Because the allocated memory will remain unrecycled for a long time, the associated resources may not be properly closed, and it is a bad habit to eat and not clean your mouth. Later, you will find that it is easy to make sure that all allocated data is properly cleared. Let's simply compare the traditional memory allocation functions (which should only be used in external libraries) with the persistent and non-persistent memory allocation functions of PHP/ZE. Traditional non-persistent malloc (count) calloc (count, num) emalloc (count) ecalloc (count, num) pemalloc (count, 1) * pecalloc (count, num, 1) strdup (str) strndup (str, len) estrdup (str) estrndup (str, len) pestrdup (str, 1) pemalloc () & memcpy () free (ptr) efree (ptr) pefree (ptr, 1) realloc (ptr, newsize) erealloc (ptr, newsize) perealloc (ptr, newsize, 1) malloc (count * num + extr) ** safe_emalloc (count, num, extr) safe_pemalloc (co Unt, num, extr) * The pemalloc () family contains a 'duration' flag to allow them to implement the functions of the corresponding non-persistent functions. For example, emalloc (1234) is the same as pemalloc (1234, 0. ** Safe_emalloc () and (in PHP 5) safe_pemalloc () perform additional detection to prevent integer overflow.
Now that you have learned some internal running theories of PHP and Zend engines, I bet you want to continue exploring and start building something. Before that, you need to collect necessary build tools and set the environment suitable for your purpose. First, you need PHP and the build tool set required by PHP. If you are not familiar with building PHP from the source code, I suggest you look at http://www.php.net/install.unix. (PHP extensions for Windows will be mentioned in future articles ). However, using PHP binary distribution packages is somewhat risky. These versions tend to ignore two important options of./configure, which are very convenient during development. The first -- enable-debug. This option will compile the additional symbolic information into the PHP Execution file, so that if a segment error occurs, you can get a kernel dump file from it, use gdb to track and find out where and why a segment error occurs. Another option depends on your PHP version. In PHP 4.3, this option is named -- enable-experimental-zts. in PHP 5 and later versions, it is -- enable-maintainer-zts. This option enables PHP to run in a multi-threaded environment and capture common program errors. However, they are harmless in non-multithreaded environments, but your extensions cannot be safely used in multi-threaded environments. Once you have used these additional options to compile PHP and install it on your development server (or workstation), you can add your first extension to it. Hello World what program design introduction can completely ignore the necessary Hello World Program? In this example, you can export the extension to a simple function, which returns a string containing "Hello World. In PHP, you may do this: <? Phpfunction hello_world () {return 'Hello world';}?> Now you will transfer it to the PHP extension. First, create a directory named hello in ext/in the directory of your PHP source tree, and enter the directory chdir. In fact, this directory can be placed in the PHP source code tree or any other place, but I want you to place it here to demonstrate an irrelevant concept that will appear in future articles. You need to create three files here: the source code file containing the hello_world function, including the referenced header files. PHP uses them to load your extensions, and phpize is used to prepare and compile your extension configuration file. Config. m4PHP_ARG_ENABLE (hello, whether to enable Hello World support, [-- enable-hello Enable Hello World support]) if test "$ PHP_HELLO" = "yes"; then AC_DEFINE (HAVE_HELLO, 1, [Whether you have Hello World]) PHP_NEW_EXTENSION (hello, hello. c, $ ext_shared) fi php_hello.h # ifndef PHP_HELLO_H # define PHP_HELLO_H 1 # define PHP_HELLO_WORLD_VERSION "1.0" # define PHP_HELLO_WORLD_EXTNAME "hello" PHP_FUNCTION (hello _ World); extern zend_module_entry hello_module_entry; # define phpext_hello_ptr & hello_module_entry # endif hello. c # ifdef HAVE_CONFIG_H # include "config. h "# endif # include" php. h "# include" php_hello.h "static function_entry hello_functions [] = {PHP_FE (hello_world, NULL) {NULL, NULL, NULL}; zend_module_entry hello_module_entry ={# if functions> = functions, # endifPHP_HELLO_WORLD_E XTNAME, hello_functions, NULL, # if ZEND_MODULE_API_NO> = upper, # endifSTANDARD_MODULE_PROPERTIES}; # ifdef evaluate (hello) # endifPHP_FUNCTION (hello_world) {RETURN_STRING ("Hello World", 1);} in the preceding example extension, most of the code you see is a binder, as a protocol language that will introduce extensions to PHP and establish sessions for communication. Only the last four lines are the codes you think are actually doing things. They are responsible for interacting with the script in the user space. The code looks exactly like the PHP code we saw before, and you can understand it at a Glance: declare a function named hello_world to let the function return the string "Hello World ".... well .... 1? What happened to that 1? Recall that ZE contains a complex memory management layer that ensures that the allocated resources are released when the script exits. However, in the memory management field, releasing the same memory twice is absolutely forbidden (big no-no ). This practice, called double freeing, is a common cause of segment errors because it allows the caller to try to access memory that is no longer in use. Similarly, you should not let ZE release a static string buffer (such as "Hello World" in our example extension) because it exists in the program space, instead of data blocks owned by any process. RETURN_STRING () can be assumed that any input string needs to be copied so that it can be safely released later. However, it is not uncommon for internal functions to dynamically allocate memory, populate, and return data to the string, the second parameter RETURN_STRING () allows us to specify whether to copy a copy of the string. To further describe this concept, the following code snippets are equivalent to the above version: PHP_FUNCTION (hello_world) {char * str; str = estrdup ("Hello World"); RETURN_STRING (str, 0);} in this version, you manually allocate memory for the string "Hello World" that will be returned to the call script, and then "RETURN_STRING ()" for the fast memory (), use the second parameter 0 to point out that it does not need to make its own copy, but it can own ours. The last step to build your extension is to build your extension into a Dynamically Loaded module. If you have copied the above Code correctly, you only need to run three commands in ext/hello/: $ phpize $. /configure -- enable-hello $ make after each command is run, you can see the file hello in the ext/hello/modules/directory. so. Now, you can copy it to your extension directory like other extensions (default:/usr/local/lib/php/extensions/, check your php. ini to confirm), put extension = hello. so add your php. ini to enable PHP to load it at startup. For CGI/CLI, the next time PHP is run, it will take effect. For web Server SAPI, such as Apache, You need to restart the web server. Now let's try it from the command line: $ php-r 'echo hello_world (); 'if everything is normal, you will see the Hello World output by this script, because the function hello_world () in your loaded extension returns this string, and the echo command outputs the content to it as is (in this example, the result of the function ). Other scalar values can be returned in the same way. The integer value is RETURN_LONG (), the floating point value is RETURN_DOUBLE (), the true/false value is RETURN_BOOL (), and The RETURN_NULL ()? You guessed it, It's NULL. Let's take a look at their respective applications in the instance. Add the corresponding lines of PHP_FE () in the function_entry structure in the file hello. c, and add some PHP_FUNCTION () at the end of the file (). Static function_entry hello_functions [] = {PHP_FE (hello_world, NULL) PHP_FE (hello_long, NULL) PHP_FE (hello_double, NULL) PHP_FE (empty, NULL) PHP_FE (hello_null, NULL) {NULL, NULL, NULL }}; PHP_FUNCTION (hello_long) {RETURN_LONG (42);} PHP_FUNCTION (hello_double) {RETURN_DOUBLE (3.1415926535);} PHP_FUNCTION (hello_bool) {RETURN_BOOL (1 );} PHP_FUNCTION (hello_null) {RETURN_NULL ();} you also need to function hello_world () in the header file php_hello.h () Add the prototype declaration of these functions next to the prototype declaration to build the process correctly: PHP_FUNCTION (hello_world); PHP_FUNCTION (hello_long); PHP_FUNCTION (hello_double); PHP_FUNCTION (hello_bool ); PHP_FUNCTION (hello_null); because you have not changed the file config. m4, skip phpize and. the/configure step is technically safe to directly jump to make. However, now I want you to finish all the building steps again to ensure that the building is good. In addition, you should call make clean all instead of simply making in the last step to ensure that all source files are rebuilt. Repeat it. So far, depending on the type of change you have done, these (Steps) are not necessary, but the security is better than obfuscation. Once the module is built, copy it to your extension directory and replace the old version. In this case, you can call the PHP interpreter again and pass in the script to test the newly added function. In fact, why not do it now? I will wait here... is it done? Okay. If var_dump () is used instead of echo to view the output of each function, you may notice that hello_bool () returns true. That is the result of 1 in RETURN_BOOL. Like in a PHP script, the integer 0 equals FALSE, while the other integers equals TRUE. Just as an agreement, expansion authors usually use 1 to encourage you to do the same, but do not feel restricted by it. For other readability purposes, you can also use macros RETURN_TRUE and RETURN_FALSE; then use hello_bool (). This time, use RETURN_TRUE: PHP_FUNCTION (hello_bool) {RETURN_TRUE;}. Note that parentheses are useless here. In that case, the RETURN_TRUE and RETURN_FALSE styles are different (are aberrations) compared with other macro RETURN ), so be sure not to be misled by it (to get caught by this one ). As you may have noticed, in each of the above examples, we did not input 0 or 1 to indicate whether to copy the data. This is because there is no need to allocate or release additional memory for small scalars like these (except for the variable container itself-we will take a deeper look in Part 2 .) There are three other return types: Resource (like the names of values returned by mysql_connect (), fsockopen (), and ftp_connect (), but not limited to), array (also called HASH) and object (returned by the keyword new ). When we explain the variables in depth, we will see them in the second part. The initial setup (INI) Zend engine provides two ways to manage INI values. Now let's take a look at the simpler method. Then, when you process global data, you can explore more sophisticated but more complex methods. Suppose you want to define a value for your extension in php. ini, hello. greeting, Which is saved as the greeting string used in the hello_world () function. You need to add some code to hello. c and php_hello.h, and make some key changes to the hello_module_entry structure. Add the following prototype to the prototype declaration of the php_hello.h file near the user space function: PHP_MINIT_FUNCTION (hello); PHP_MSHUTDOWN_FUNCTION (hello); PHP_FUNCTION (hello_world); PHP_FUNCTION (hello_long ); PHP_FUNCTION (hello_double); PHP_FUNCTION (hello_bool); PHP_FUNCTION (hello_null); now enters the file hello. c. Remove hello_module_entry of the current version and replace it with the following list: zend_module_entry hello_module_entry ={# if ZEND_MODULE_API_NO> = 20010901STANDARD_MODULE_HEADER, # emerge, he Maid, PHP_MINIT (hello), PHP_MSHUTDOWN (hello), NULL, # if exist> = partition, # endifSTANDARD_MODULE_PROPERTIES}; PHP_INI_BEGIN () PHP_INI_ENTRY ("hello. greeting "," Hello World ", PHP_INI_ALL, NULL) PHP_INI_END () PHP_MINIT_FUNCTION (hello) {REGISTER_INI_ENTRIES (); return SUCCESS;} PHP_MSHUTDOWN_FUNCTION (hello) {response (); return SUCCESS;} Now, you only need Ello. add a # include file next to the # include file at the top of c to obtain the correct header file that supports INI: # ifdef HAVE_CONFIG_H # include "config. h "# endif # include" php. h "# include" php_ini.h "# include" php_hello.h ". Finally, you can modify the hello_world function to use the INI value: PHP_FUNCTION (hello_world) {RETURN_STRING (INI_STR (" hello. greeting "), 1) ;}note that you want to copy the value returned from INI_STR. This is because, before entering the PHP variable stack (as far as the PHP variable stack is concerned), it is a static string. In fact, if you try to modify the returned string, the PHP Execution Environment may become unstable or even crash. The first change in this section introduces two functions that you are very familiar with: MINIT and MSHUTDOWN. As mentioned earlier, these methods are called respectively during the initial start and end of SAPI. They are not called between the request period and the request. In this example, they are used to register the entries defined in your extension with php. ini. Later in this series, you will also see how to use MINIT and MSHUTDOWN functions to register resources, objects, and stream processors. Use INI_STR () in the hello_world () function to obtain the current string value of the hello. greeting entry. Other similar functions are used to obtain values of other types, such as long integer, Double Precision Floating Point, and Boolean, as shown in the following table. Other ORIG versions are also provided in php. INI (original) settings in the INI file (before. htaccess or ini_set () command before changing) (Original: provides the value of the referenced INI setting as it was set in php. ini- ). Original Value Type INI_STR (name) INI_ORIG_STR (name) char * (NULL terminated) INI_INT (name) INI_ORIG_INT (name) signed longINI_FLT (name) INI_ORIG_FLT (name) signed doubleINI_BOOL (name) INI_ORIG_BOOL (name) zend_bool the first parameter passed into PHP_INI_ENTRY () is included in php. name string used in the INI file. To avoid namespace conflicts, you should use the same conventions as the function, that is, using your extension name as the prefix of all values, just as you did for hello. greeting. As an convention, a period is used to separate extended names and more descriptive initial names. The second parameter is the initial value (default value? And, whether it is a numeric value or not, use a char * string. This is mainly based on the fact that the original value in the. ini file is text-and everything else is stored as a text file. The INI_INT (), INI_FLT (), and INI_BOOL () types used in the subsequent scripts will be converted. The third value passed in is the access mode modifier. This is a bit mask field that determines when and where the INI value can be modified. For some of them, such as register_globals, it only does not allow ini_set () in the script to change this value, because this setting only makes sense during the request startup (before the script can run. Others, such as allow_url_fopen, are management (only available for members) settings. You do not want users who share the host environment to modify it, whether through ini_set () or. htaccess commands. The typical value of this parameter may be PHP_INI_ALL, indicating that the value can be modified anywhere. There is also PHP_INI_SYSTEM | PHP_INI_PERDIR, indicating that this setting can be modified in the php. ini file, or through the Apache command in the. htaccess file, but cannot be modified using ini_set. Alternatively, you can use PHP_INI_SYSTEM to indicate that the value can only be modified in the php. ini file, rather than anywhere else. We ignore the fourth parameter, just to mention that it allows a method callback to be triggered when the initial setting changes, for example, using ini_set. This allows the extension to perform more precise control when the settings change, or trigger a related action based on the new settings. Global numeric expansion often requires that a value be tracked by the distinct operator in a specific request and separated from other requests that may occur at the same time. In a non-multithreading SAPI, it is simple: declare a global variable in the source file and access it as needed. The problem is that, because PHP is designed to run in a multi-threaded web server (such as Apache 2 and IIS), it must maintain the independence of the global values used by each thread. By using the TSRM (Thread Safe Resource Management, Thread-Safe Resource Manager) abstraction layer-sometimes called ZTS (Zend Thread Safety, Zend Thread security), PHP greatly simplifies it. In fact, you have used some TSRM, but you are not aware of it. (Do not look too hard. As this series goes on, you will see it everywhere .) Like any global scope, the first step in creating a thread-safe scope is to declare it. For the purpose of this example, you will declare a long global value with a value of 0. Every time hello_long () is called, this value is increased by 1 and return. Add the following code snippet to the # define PHP_HELLO_H statement in the php_hello.h file: # ifdef ZTS # include "TSRM. h "# counter (hello) long counter; counter (hello) # ifdef ZTS # define HELLO_G (v) TSRMG (hello_globals_id, zend_hello_globals *, v) # else # define HELLO_G (v) (hello_globals.v) # endif this time also uses the RINIT method, so you need to declare its prototype in the header file: PHP_MINIT_FUNCTION (hello); PHP_MSHUTDOWN_FUNCTION (hello); PHP_RINIT_FUNCTION (hello ); now let's go back File hello. c and add the following code after the code block: # ifdef HAVE_CONFIG_H # include "config. h "# endif # include" php. h "# include" php_ini.h "# include" php_hello.h "Modify (hello) Change hello_module_entry and add PHP_RINIT (hello): zend_module_entry hello_module_entry ={# if exist> = strong, # Strong, hello_functions, PHP_MINIT (hello), PHP_MSHUTDOWN (hello), PHP_RINIT (he Llo), NULL, NULL, # if ZEND_MODULE_API_NO> = 20010901PHP_HELLO_WORLD_VERSION, # endifSTANDARD_MODULE_PROPERTIES}; modify your MINIT function with two other functions that execute initialization at request startup: static void Merge (zend_hello_globals * hello_globals) {} PHP_RINIT_FUNCTION (hello) {HELLO_G (counter) = 0; return SUCCESS;} PHP_MINIT_FUNCTION (hello) {hello, Alipay, NULL ); REGISTER_INI_ENTRIES (); return SU CCESS;} Finally, you can modify the hello_long () function to use this value: PHP_FUNCTION (hello_long) {HELLO_G (counter) ++; RETURN_LONG (HELLO_G (counter ));} in the code you added to php_hello.h, you used two macros-ZEND_BEGIN_MODULE_GLOBALS () and ZEND_END_MODULE_GLOBALS ()-to create a structure named zend_hello_globals, which contains a long variable. Then, define HELLO_G () as a condition to get a value from the thread pool or get it from the global scope-if your compilation target is a non-multi-threaded environment. In hello. c, you use the ZEND_DECLARE_MODULE_GLOBALS () macro to demonstrate the zend_hello_globals structure, or the global structure (if this construction is not thread-safe), or a member of the thread's resource pool. As an extension author, we don't need to worry about their differences, because the Zend engine takes care of this. Finally, you use ZEND_INIT_MODULE_GLOBALS () in MINIT to allocate a thread-safe resource id-you do not need to consider what it is. You may have noticed that php_hello_init_globals () didn't actually do anything, but declared a RINIT to initialize the variable counter to 0. Why? The key is when these two functions are called. Php_hello_init_globals () is called only when a new process or thread starts. However, each process can process multiple requests, therefore, using this function to initialize the variable counter to 0 will only run at the first page request. Subsequent page requests sent to the same process will still get the counter variable value stored here, so the count will not start from 0. To initialize the counter variable to 0 for each page request, we implement the RINIT function. As we can see earlier, it is called before each page request. In this case, we include the php_hello_init_globals () function because you will use it later, and inputting NULL for this initialization function in ZEND_INIT_MODULE_GLOBALS () will cause a segment error on a non-multithreading platform. The initial setting (INI) is used as a global value. In retrospect, a php statement declared using PHP_INI_ENTRY. the ini value is parsed as a string and converted to other formats as needed: INI_INT (), INI_FLT (), and INI_BOOL. For some settings, perform a lot of unnecessary repetitive work when reading these values during script execution. Fortunately, ZE can store the INI value as a specific data type and perform type conversion only when its value is changed. We try to declare another INI value. This time is a Boolean value to indicate whether the variable counter is increasing or decreasing. First, change the MODULE_GLOBALS block in php_hello.h to the following code: Begin (hello) long counter; zend_bool direction; ZEND_END_MODULE_GLOBALS (hello). Next, modify the PHP_INI_BEGIN () block and declare the INI, like this: PHP_INI_BEGIN () PHP_INI_ENTRY ("hello. greeting "," Hello World ", PHP_INI_ALL, NULL) STD_PHP_INI_ENTRY (" hello. direction "," 1 ", PHP_INI_ALL, OnUpdateBool, direction, zend_hello_globals, hello_globals) PHP_INI_END () now use the following code to initialize init_globa Set in the ls method: static void php_hello_init_globals (zend_hello_globals * hello_globals) {hello_globals-> direction = 1;}. Finally, in hello_long () to determine whether to increment or decrease: PHP_FUNCTION (hello_long) {if (HELLO_G (direction) {HELLO_G (counter) ++;} else {HELLO_G (counter) --;} RETURN_LONG (HELLO_G (counter. The OnUpdateBool method specified in the INI_ENTRY section automatically loads php. ini ,. htaccess or convert the values provided by ini_set () in the script to the appropriate TRUE/FALSE values, so that you can directly access them in the script. The last three parameters of STD_PHP_INI_ENTRY tell PHP which global variable to change, what is the structure of our extended global (scope), and what is the name of the global scope that holds these variables. Check (CODE) integrity so far, our three files should be similar to the following list. (For readability, some projects are moved and reorganized .) Config. m4PHP_ARG_ENABLE (hello, whether to enable Hello World support, [-- enable-hello Enable Hello World support]) if test "$ PHP_HELLO" = "yes"; then AC_DEFINE (HAVE_HELLO, 1, [Whether you have Hello World]) PHP_NEW_EXTENSION (hello, hello. c, $ ext_shared) fi php_hello.h # ifndef PHP_HELLO_H # define PHP_HELLO_H 1 # ifdef ZTS # include "TSRM. h "# counter (hello) long counter; zend_bool direction; ZEND_END_MODULE_GLOBALS (hello) # ifdef ZTS # define HELLO_G (v) TSRMG (hello_globals_id, zend_hello_globals) # else # define HELLO_G (v) (hello_globals.v) # endif # define tuning "1.0" # define tuning "hello" PHP_MINIT_FUNCTION (hello); PHP_MSHUTDOWN_FUNCTION (hello); PHP_RINIT_FUNCTION (hello ); PHP_FUNCTION (hello_world); PHP_FUNCTION (hello_long); PHP_FUNCTION (hello_double); PHP_FUNCTION (hello_bool); PHP_FUNCTION (hello_null); extern ready functions; # define functions & features # endif hello. c # ifdef HAVE_CONFIG_H # include "config. h "# endif # include" php. h "# include" example "# include" php_hello.h "example (hello) static function_entry hello_functions [] = {PHP_FE (hello_world, NULL) PHP_FE (hello_long, NULL) PHP_FE (hello_double, NULL) PHP_FE (hello_bool, NULL) PHP_FE (hello_null, NULL) {NULL, NULL, NULL }}; zend_module_entry hello_module_entry ={# if role >=20010901standard_module_header, # role, hello_functions, PHP_MINIT (hello), PHP_MSHUTDOWN (hello), PHP_RINIT (hello), NULL, NULL, # if exist> = enabled, # endifSTANDARD_MODULE_PROPERTIES}; # ifdef evaluate (hello) # endifPHP_INI_BEGIN () PHP_INI_ENTRY ("hello. greeting "," Hello World ", PHP_INI_ALL, NULL) STD_PHP_INI_ENTRY (" hello. direction "," 1 ", PHP_INI_ALL, OnUpdateBool, direction, direction, hello_globals) PHP_INI_END () static void merge (direction * hello_globals) {hello_globals-> direction = 1 ;} PHP_RINIT_FUNCTION (hello) {HELLO_G (counter) = 0; return SUCCESS;} PHP_MINIT_FUNCTION (hello) {response (hello, php_hello_init_globals, NULL); Response (); return SUCCESS ;} PHP_MSHUTDOWN_FUNCTION (hello) {UNREGISTER_INI_ENTRIES (); return SUCCESS;} PHP_FUNCTION (hello_world) {RETURN_STRING ("Hello World", 1);} PHP_FUNCTION (hello_long) {if (HELLO_G (direction) {HELLO_G (counter) ++;} else {HELLO_G (counter) --;} RETURN_LONG (HELLO_G (counter);} PHP_FUNCTION (hello_double) {RETURN_DOUBLE (3.1415926535);} PHP_FUNCTION (hello_bool) {RETURN_BOOL (1);} PHP_FUNCTION (hello_null) {RETURN_NULL ();}
What is next? This tutorial explores a simple PHP extension structure, including exporting functions, return values, declaring initial settings (INI), and tracking internal states during (client) requests. In the next section, we will explore the internal structure of PHP variables and how to store, track, and maintain them in the script environment. When a function is called, we will use zend_parse_parameters to receive parameters from the program and explore how to return more complex results, including arrays, objects, and the resources mentioned in this tutorial.