Home > Article > Backend Development > Automatic generation of extension framework for php extension
Previous article: Novice learns PHP extension: hello world. Regardless of the reason, he forcibly says hello with PHP extension. The framework automatically generated by ext_skel will be explained in detail in this article as a memo.
./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help] --extname=module module is the name of your extension(模块名,会在当前目录创建一个该名称子目录) --proto=file file contains prototypes of functions to create(函数原型定义文件) --stubs=file generate only function stubs in file --xml generate xml documentation to be added to phpdoc-cvs --skel=dir path to the skeleton directory(设置骨架生成的目录,不设置该项则默认在ext/extname下) --full-xml generate xml documentation for a self-contained extension (not yet implemented) --no-help don't try to be nice and create comments in the code and helper functions to test if the module compiled (生成的代码中不显示各种帮助注释)
1. The startup and termination of the PHP program are conceptually separate. of.
One is when the php module is loaded, the module startup function is called by the engine (PHP_MINIT_FUNCTION). This causes the engine to do some initialization such as resource types, registering INI variables, etc., and these data are resident in memory, corresponding to a termination (PHP_MSHUTDOWN_FUNCTION)
The other is when the PHP request starts, the request Don't call the previous startup function (PHP_RINIT_FUNCTION), which corresponds to the termination after the request is completed (PHP_RSHUTDOWN_FUNCTION)
2. As PHP starts, it will start to process the MINIT method of all its loaded extensions. (The full name is Module Initialization, which is a function defined by each module.) (PHP_MINIT_FUNCTION), execute it once. During this time, the extension can define some of its own constants, classes, resources, etc., all of which will be used by the user-side PHP script. s things. The stuff defined here will be resident in memory and can be used by all requests until the PHP module is turned off.
3. When a request comes, PHP will quickly open up a new environment, rescan its own extensions, and traverse and execute their respective RINIT methods (full name Request Initialization) (PHP_RINIT_FUNCTION). At this time, a The extension may initialize variables that will be used in this request, etc., and may also initialize variables in the client (i.e. PHP script) later, etc.
4. When the request passes through the business code and is executed to the end, PHP will start the recycling program and execute the RSHUTDOWN (full name Request Shutdown) (PHP_RSHUTDOWN_FUNCTION) method of all loaded extensions, using variables in the kernel Once the execution is completed, everything used in this request will be released, including all variables in the variable table, all memory requested in this request, etc.
5 After the request processing is completed, the ones that should be closed are also closed, and PHP will enter the MSHUTDOWN (full name Module Shutdown) (PHP_MSHUTDOWN_FUNCTION) stage. At this time, PHP will issue an ultimatum to all extensions. If any extension still has unfulfilled wishes, let it go. In its own MSHUTDOWN method, this is the last chance. Once PHP finishes executing the extended MSHUTDOWN, it will enter the self-destruct program. (The last chance to clear the memory applied for without authorization, otherwise the memory will leak)
Summary, the process I understand:
PHP_MINIT_FUNCTION (executed once per process)
|
Execute many PHP_RINIT_FUNCTION
|
Execute many PHP_RSHUTDOWN_FUNCTION
|
PHP_MSHUTDOWN_FUNCTION (executed once per process)
Attached are the diagrams of multi-threading and multi-process
dnl $Id$ dnl config.m4 for extension helloworld dnl Comments in this file start with the string 'dnl'. dnl Remove where necessary. This file will not work dnl without editing. dnl If your extension references something external, use with:##指定PHP模块的工作方式,动态编译选项,如果想通过.so的方式接入扩展,请去掉前面的dnl注释PHP_ARG_WITH(helloworld, for helloworld support, Make sure that the comment is aligned: [ --with-helloworld Include helloworld support]) dnl Otherwise use enable:##指定PHP模块的工作方式,静态编译选项,如果想通过enable的方式来启用,去掉dnl注释PHP_ARG_ENABLE(helloworld, whether to enable helloworld support, Make sure that the comment is aligned: [ --enable-helloworld Enable helloworld support])if test "$PHP_HELLOWORLD" != "no"; then dnl Write more examples of tests here... dnl # --with-helloworld -> check with-path dnl SEARCH_PATH="/usr/local /usr" # you might want to change this dnl SEARCH_FOR="/include/helloworld.h" # you most likely want to change this dnl if test -r $PHP_HELLOWORLD/$SEARCH_FOR; then # path given as parameter dnl HELLOWORLD_DIR=$PHP_HELLOWORLD dnl else # search default path list dnl AC_MSG_CHECKING([for helloworld files in default path]) dnl for i in $SEARCH_PATH ; do dnl if test -r $i/$SEARCH_FOR; then dnl HELLOWORLD_DIR=$i dnl AC_MSG_RESULT(found in $i) dnl fi dnl done dnl fi dnl dnl if test -z "$HELLOWORLD_DIR"; then dnl AC_MSG_RESULT([not found]) dnl AC_MSG_ERROR([Please reinstall the helloworld distribution]) dnl fi dnl # --with-helloworld -> add include path dnl PHP_ADD_INCLUDE($HELLOWORLD_DIR/include) dnl # --with-helloworld -> check for lib and symbol presence dnl LIBNAME=helloworld # you may want to change this dnl LIBSYMBOL=helloworld # you most likely want to change this dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, dnl [ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $HELLOWORLD_DIR/$PHP_LIBDIR, HELLOWORLD_SHARED_LIBADD) dnl AC_DEFINE(HAVE_HELLOWORLDLIB,1,[ ]) dnl ],[ dnl AC_MSG_ERROR([wrong helloworld lib version or lib not found]) dnl ],[ dnl -L$HELLOWORLD_DIR/$PHP_LIBDIR -lm dnl ]) dnl ##用于说明这个扩展编译成动态链接库的形式 dnl PHP_SUBST(HELLOWORLD_SHARED_LIBADD) ##用于指定有哪些源文件应该被编译,文件和文件之间用空格隔开 PHP_NEW_EXTENSION(helloworld, helloworld.c, $ext_shared)fiphp_helloworld.hI found that many textbooks written long ago on the Internet have functions declared in the header file. It seems that newer versions do not require it. Because the framework generated by default does not see words like "PHP_FUNCTION(confirm_helloworld_compiled)" in the header file. So don't worry too much about this file. (But it is a good practice to declare the function to be implemented in the header file) Know that the version number that will be used below helloworld.c is defined here
#define PHP_HELLOWORLD_VERSION "0.1.0"helloworld.cCode structureMany macros of PHP_XXX are defined in main/php.h
#ifdef HAVE_CONFIG_H #include "config.h" #endif ##包含头文件(引入所需要的宏、API定义等) #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_helloworld.h" static int le_helloworld; ##PHP核心定义的一个宏,与ZEND_FUNCTION相同,用于定义扩展函数(这个函数是系统默认生成的,用于确认之用) PHP_FUNCTION(confirm_helloworld_compiled) { char *arg = NULL; int arg_len, len; char *strg; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "helloworld", arg); RETURN_STRINGL(strg, len, 0); } ##定义PHP中可以调用的函数 PHP_FUNCTION(helloworld) { php_printf("Hello World!\n"); RETURN_TRUE; } ##初始化module时运行 PHP_MINIT_FUNCTION(helloworld) { /* If you have INI entries, uncomment these lines REGISTER_INI_ENTRIES(); */ return SUCCESS; } ##当module被卸载时运行 PHP_MSHUTDOWN_FUNCTION(helloworld) { /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ return SUCCESS; } ##当一个REQUEST请求初始化时运行 PHP_RINIT_FUNCTION(helloworld) { return SUCCESS; } ##当一个REQUEST请求结束时运行 PHP_RSHUTDOWN_FUNCTION(helloworld) { return SUCCESS; } ##声明模块信息函数,即可以在phpinfo看到的信息 PHP_MINFO_FUNCTION(helloworld) { php_info_print_table_start(); php_info_print_table_header(2, "helloworld support", "enabled"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } ##声明(引入)Zend(PHP)函数块 const zend_function_entry helloworld_functions[] = { PHP_FE(confirm_helloworld_compiled, NULL) /* For testing, remove later. */ ##上一讲中就是在这里添加了自己定义的函数模块 PHP_FE(helloworld, NULL) /* */ ##zend引擎认为结束的标记,老版本的是“{NULL,NULL,NULL}”,后面PHP源代码直接定义了个宏PHP_FE_END,这里就直接用这个了。虽然都一个意思但看过去爽多了 ##如果遇到PHP_FE_END未定义undefine的问题,请见附录1 PHP_FE_END /* Must be the last line in helloworld_functions[] */ }; ##声明 Zend模块,是不是感觉下面的模块名字很熟悉,对的,就是前文讲到的PHP流程中会用到的,现在懂了为什么要先讲流程了吧~ zend_module_entry helloworld_module_entry = { STANDARD_MODULE_HEADER, "helloworld", helloworld_functions, PHP_MINIT(helloworld), PHP_MSHUTDOWN(helloworld), PHP_RINIT(helloworld), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(helloworld), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(helloworld), PHP_HELLOWORLD_VERSION, STANDARD_MODULE_PROPERTIES }; ##实现get_module()函数 #ifdef COMPILE_DL_HELLOWORLD ZEND_GET_MODULE(helloworld) #endifModule structure1. Include the header file (introduce the required macros , API definition, etc.); The header file that must be included in the module is only one php.h, which is located in the main directory. This file contains various macros and API definitions necessary to build the module. 2. Declare exported functions (for declaration of Zend function blocks); ZEND_FUNCTION macro declares a new C function compiled using Zend internal API. This C function is of type void, takes INTERNAL_FUNCTION_PARAMETERS (this is another macro) as parameters, and the function name is prefixed with zif_.
PHP_FUNCTION is the same as this. The macro has been defined in /main/php.h
#define PHP_FUNCTION ZEND_FUNCTION3. Declare the Zend function block; Now you have declared the exported function , but Zend doesn't know how to call it, so it must be introduced into Zend. The introduction of these functions is completed through an array containing N zend_function_entry structures. Each item in the array corresponds to an externally visible function, and each item contains the name of a function as it appears in PHP and the name defined in C code. 4. Declare Zend module; Zend module information is saved in a structure called zend_module_entry, which contains all module information that needs to be provided to Zend. 5. Implement the get_module() function;
这个函数只用于动态可加载模块
6.实现导出函数。
实现想要扩展的函数,PHP_FUNCTION(helloworld)
ps:模块部分是学习这篇文章的,本来写好了,后面发现他写的比我好就借鉴了PHP扩展代码结构详解
1.error: ‘PHP_FE_END’ undeclared here (not in a function)错误。
原因:是因为zend引擎版本太老了。
1、切换到php的源码目录,
2、执行下面两行
# sed -i 's|PHP_FE_END|{NULL,NULL,NULL}|' ./ext/**/*.c # sed -i 's|ZEND_MOD_END|{NULL,NULL,NULL}|' ./ext/**/*.c
3.切换到mcrypt目录,如php-5.x.x/ext/mcrypt/。再次执行make命令,一切恢复正常。
The above is the detailed content of Automatic generation of extension framework for php extension. For more information, please follow other related articles on the PHP Chinese website!