Summary & Introduction
PHP is currently widely used in a language, from the foreign Facebook, Twitter to the domestic Taobao, Tencent, Baidu and then to the internet a variety of large and medium-sized sites can see its figure. PHP's success, it should be said, relies heavily on its open extension API mechanism and rich extension components (PHP Extension), which enable PHP to do everything from various database operations to XML, JSON, encryption, file processing, graphics processing, sockets, and more. Sometimes developers may need to develop their own PHP extensions, the current PHP5 extension mechanism is based on the Zend API, the Zend API provides rich interface and macro definitions, plus a number of utilities, making PHP expansion is not particularly difficult to develop. This article will introduce you to the basics of the development of PHP extensions and demonstrate an example of the basic process of developing PHP extensions.
The development process of the PHP extension component is different in Unix and Windows, but is basically interoperable, and this article will be based on the UNIX environment (using Linux specifically). Reading this article requires a simple understanding of the basics of the UNIX environment, PHP, and C, as long as it is simple to understand, I will try not to involve too specific operating system and language features, and explain them where necessary so that readers can read them.
The specific development environment of this article is Ubuntu 10.04 + PHP 5.3.3.
Download PHP source code
To develop the PHP extension, the first step is to download the PHP source code, because there are tools to develop the expansion needs. I downloaded the latest version of PHP 5.3.3, the format is tar.bz2 compression package. The download address is: Http://cn.php.net/get/php-5.3.3.tar.bz2/from/a/mirror.
After downloading, move the source code to the appropriate directory and unzip it. The decompression command is:
Copy CodeThe code is as follows: TAR-JXVF Source package Name
If the download is tar.gz compression package, decompression command for
Copy CodeThe code is as follows: TAR-ZXVF Source package Name
After decompression, there is an ext directory in the source code directory, this is the directory related to the PHP extension. After entering the directory with LS view, you can see many existing extensions. The following figure is the result of viewing in my environment:
Where the blue is the expansion package directory, which can see we are very familiar with MySQL, Iconv and GD and so on. Ext_skel is a scripting tool for automatically generating PHP extensions in a UNIX environment, which we'll soon use, ext_skel_win32.php is the corresponding script under Windows.
Develop your own PHP extensions--say_hello
Here we develop a PHP extension: Say_hello. This extension is very simple, just accept a string parameter, and then output "Hello xxx!". This example is just to introduce the development process of the PHP extension component, not to assume the actual function.
Build Extension Component Framework
PHP extension Component Development directory and file is a fixed organizational structure, you can casually enter an existing extension directory to view all its files, I think you must be dazzled. Of course you can choose to finish the frame by hand, but I'm sure you'd rather have something to help you do it. The Ext_skel script mentioned above is the tool used to automatically build the expansion pack framework. The complete command for Ext_skel is:
Ext_skel--extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help]
As beginners, we don't have to know all the command parameters, in fact, in most cases we just need to provide the first parameter, that is, the extension module's name. Therefore, we type the following command in the EXT directory:
./ext_skel--extname=say_hello
(If you would like to know more about Ext_skel's command parameters, please refer here)
Then use LS to view, will find more than a "Say_hello" directory, enter this directory, will find Ext_skel has been for us to establish a Say_hello basic framework, the following figure:
If you don't bother to figure out the entire contents of the PHP Expansion pack directory structure, there are three files that you must be aware of:
CONFIG.M4: This is the build system configuration file in the UNIX environment, which will be used to generate configuration and installation later.
Php_say_hello.h: This file is the header file for the extension module. Follow the usual style of C language, which can be placed in a number of custom structure, global variables and so on.
SAY_HELLO.C: This is the main program file for the extension module, and the final extension module is here for each function entry. Of course, you can plug all of the program code into here, or follow the modular thinking, the various functional modules into different files.
The following content is primarily centered around these three files.
Unix Build System Configuration
The first step in developing a PHP extension component is not to write implementation code, but to configure the build System option first. Since we are developing under Linux, the configuration here is mainly related to CONFIG.M4.
About build system configuration this piece, if write can write a lot of, and with many things in Unix system, even if I am interested in writing estimates are not interested in reading, so here we Conlio, just pick the key place to say, about CONFIG.M4 more details can refer to here.
Open the generated config.m4 file, which is roughly as follows:
Copy CodeThe code is as follows:
DNL $Id $
DNL config.m4 for extension Say_hello
DNL Comments In this file, start with the string "DNL".
DNL Remove where necessary. This file is not work
DNL without editing.
DNL If your extension references something external, use with:
DNL Php_arg_with (Say_hello, for Say_hello support,
DNL Make sure this comment is aligned:
DNL [--with-say_hello Include Say_hello support])
DNL otherwise use enable:
DNL php_arg_enable (Say_hello, whether to ENABLE Say_hello support,
DNL Make sure this comment is aligned:
DNL [--enable-say_hello enable Say_hello support])
if test "$PHP _say_hello"!= "no"; Then
DNL Write More examples of tests ...
DNL #--with-say_hello-> Check With-path
DNL search_path= "/USR/LOCAL/USR" # you might want to change this
DNL search_for= "/include/say_hello.h" # you most likely want to change this
DNL if Test-r $PHP _say_hello/$SEARCH _for; Then # path given as parameter
DNL say_hello_dir= $PHP _say_hello
DNL Else # Search default Path list
DNL ac_msg_checking ([for Say_hello files in default path])
DNL for i in $SEARCH _path; Todo
DNL if Test-r $i/$SEARCH _for; Then
DNL say_hello_dir= $i
DNL Ac_msg_result (found in $i)
Dnl fi
DNL Done
Dnl fi
Dnl
DNL if Test-z "$SAY _hello_dir"; Then
DNL Ac_msg_result ([not found])
DNL Ac_msg_error ([Please reinstall the Say_hello distribution])
Dnl fi
DNL #--with-say_hello-> add include path
DNL php_add_include ($SAY _hello_dir/include)
DNL #--with-say_hello-> check for Lib and symbol presence
DNL Libname=say_hello # You'll want to the change this
DNL Libsymbol=say_hello # You most likely want to change this
DNL php_check_library ($LIBNAME, $LIBSYMBOL,
DNL [
DNL Php_add_library_with_path ($LIBNAME, $SAY _hello_dir/lib, Say_hello_shared_libadd)
DNL Ac_define (have_say_hellolib,1,[])
DNL],[
DNL Ac_msg_error ([wrong Say_hello Lib version or Lib not found])
DNL],[
Dnl-l$say_hello_dir/lib-lm
DNL])
Dnl
DNL Php_subst (Say_hello_shared_libadd)
Php_new_extension (Say_hello, say_hello.c, $ext _shared)
Fi
The structure may seem a bit annoying, but I'll explain what's inside. Because this is the prototype of PHP extension, if you do not understand, you can not develop PHP extension. Of course, I'm not going to explain each of the fields, just pick the key fields that this article will use, because many of the fields do not require manual filling, but can be populated with certain predefined macros.
The 7th Field "name", which is the name of this PHP extension, is "Say_hello" in this case.
The 8th Field "Functions", which will hold our reference to the functions defined in this extension, the structure is no longer analyzed, and interested friends can read the _zend_function_entry source code. When you write the code, there will be a corresponding macro.
The 第9-12个 field is four function pointers, and these four functions are invoked at the appropriate time, namely, "Extended module loading," "Extension module unload," "at the start of each request" and "at the end of each request." These four functions can be regarded as a kind of interception mechanism, which is mainly used for resource allocation, release and other related operations in the appropriate time.
The 13th field "Info_func" is also a function pointer to a function that is invoked when the phpinfo () is executed to display the custom module information.
The 14th field, "Version", is the version of the module.
(For a more detailed description of Zend_module_entry please refer to here)
The above fields are covered and we can look at the "Say_hello_module_entry" framework code that is automatically generated in "SAY_HELLO.C".
Copy Code code as follows:
/* {{say_hello_module_entry
/
Zend_module_entry say_hello_module_entry = {
#if Z End_module_api_no >= 20010901
Standard_module_header,
#endif
Say_hello,
Say_hello_functions,
Php_minit (Say_hello),
Php_mshutdown (Say_hello),
Php_rinit (Say_hello),/* Replace with NULL if there "s Nothing to do at request start/
Php_rshutdown (Say_hello),/* Replace with NULL if there ' s nothing to does at request E nd */
Php_minfo (Say_hello),
#if zend_module_api_no >= 20010901
"0.1",/* Replace with version number for yo ur extension * *
#endif
Standard_module_properties
};
/*}}} * *
First, the macro "Standard_module_header" generates the first 6 fields, and "standard_module_properties" generates the fields after "version", so now we don't have to worry about it. Several of the fields we care about are also filled in or made up by the macro, and several function frames are generated in the corresponding position of "say_hello.c". Note here, a few macro parameters are "Say_hello", but this does not mean that the names of several functions are all "Say_hello", the C language can not exist the function name overload mechanism. In fact, in the process of developing PHP extension, almost everywhere to use the Zend of predefined macros, from global variables to the definition of functions and even return values, can not be "naked" to write the C language, this is because the operating mechanism of PHP may lead to naming conflicts and other issues, These macros transform elements such as functions into an internal name, but these are transparent to programmers (unless you read the code for those macros), we program through various macros, and macros handle a lot of internal things for us.
Writing here, our task is clear: first, if you need to deal with some things at the appropriate time, then need to fill in the contents of the interception function; second, write the Say_hello function and add the reference to the say_hello_functions.
Writing phpinfo () callback functions
Because the Say_hello extension does not need to be done at each lifecycle stage, we only write the content of Info_func, which, as mentioned above, is automatically invoked when Phpinfo () executes, to display the extended information. Writing this function will use four functions:
Php_info_print_table_start ()--Start phpinfo table. No parameters.
Php_info_print_table_header ()--Outputs the table header. The first parameter is an integer that indicates the number of columns in the header, and then the following argument is the same as the number of columns (char*) type parameter used to specify the text to display.
Php_info_print_table_row ()--outputs the table contents. The first parameter is an integer that indicates the number of columns in the row, and then the following argument is the equivalent of the number of columns (char*) type parameter used to specify the text to display.
Php_info_print_table_end ()--Ends the Phpinfo table. No parameters.