Heim > Artikel > Backend-Entwicklung > Automatische Generierung eines Erweiterungsframeworks für PHP-Erweiterungen
Vorheriger Artikel: Anfänger lernt PHP-Erweiterung – hallo Welt Egal aus welchem Grund, er sagt gewaltsam Hallo zur PHP-Erweiterung. Das von ext_skel automatisch generierte Framework wird in diesem Artikel als Memo ausführlich erläutert.
./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. Der Start und die Beendigung von PHP-Programmen sind dort konzeptionell unterschiedlich sind zwei.
Zum einen wird beim Laden des PHP-Moduls die Modulstartfunktion von der Engine aufgerufen (PHP_MINIT_FUNCTION). Dadurch kann die Engine einige Initialisierungen wie Ressourcentypen, Registrierung von INI-Variablen usw. durchführen, und diese Daten sind im Speicher resident, was einer Beendigung entspricht (PHP_MSHUTDOWN_FUNCTION)
Die andere ist, wenn die PHP-Anfrage startet, die Anfrage Rufen Sie nicht die vorherige Startfunktion (PHP_RINIT_FUNCTION) auf, die der Beendigung nach Abschluss der Anfrage entspricht (PHP_RSHUTDOWN_FUNCTION)
2. Wenn PHP startet, beginnt es mit der Verarbeitung aller seiner MINIT-Methoden geladene Erweiterungen. (Der vollständige Name ist Modulinitialisierung, eine von jedem Modul definierte Funktion.) (PHP_MINIT_FUNCTION), während dieser Zeit kann die Erweiterung einige ihrer eigenen Konstanten, Klassen, Ressourcen usw. definieren. All dies wird vom benutzerseitigen PHP-Skript verwendet. Die hier definierten Inhalte bleiben im Speicher und können von allen Anfragen verwendet werden, bis das PHP-Modul ausgeschaltet wird.
3. Wenn eine Anfrage eingeht, öffnet PHP schnell eine neue Umgebung, scannt seine eigenen Erweiterungen erneut und führt ihre jeweiligen RINIT-Methoden (vollständiger Name Request Initialization) aus (PHP_RINIT_FUNCTION). Die Erweiterung kann Variablen initialisieren, die in dieser Anfrage usw. verwendet werden, und kann später auch Variablen im Client (z. B. PHP-Skript) usw. initialisieren.
4. Wenn die Anfrage den Geschäftscode durchläuft und bis zum Ende ausgeführt wird, startet PHP das Recyclingprogramm und führt die Methode RSHUTDOWN (vollständiger Name Request Shutdown) (PHP_RSHUTDOWN_FUNCTION) unter Verwendung von Variablen aus Machen Sie im Kernel so etwas wie eine Tabelle. Sobald die Ausführung abgeschlossen ist, wird alles, was in dieser Anfrage verwendet wird, freigegeben, einschließlich aller Variablen in der Variablentabelle, des gesamten in dieser Anfrage angeforderten Speichers usw.
5 Danach Die Anforderungsverarbeitung ist abgeschlossen, diejenigen, die geschlossen werden sollten, werden ebenfalls geschlossen, und PHP tritt in die Phase MSHUTDOWN (vollständiger Name des Moduls Shutdown) (PHP_MSHUTDOWN_FUNCTION) ein. Zu diesem Zeitpunkt stellt PHP allen Erweiterungen ein Ultimatum hat unerfüllte Wünsche, lassen Sie es los. In seiner eigenen MSHUTDOWN-Methode ist dies die letzte Chance. Sobald PHP die Ausführung des erweiterten MSHUTDOWN beendet hat, tritt es in das Selbstzerstörungsprogramm ein. (Letzte Chance, nicht autorisierten Speicher zu löschen, sonst geht Speicher verloren)
Zusammenfassung, der Prozess, den ich verstehe:
PHP_MINIT_FUNCTION (wird einmal pro Prozess ausgeführt)
|.
Führen Sie viele PHP_RINIT_FUNCTION
aus
|.
Führen Sie viele PHP_RSHUTDOWN_FUNCTION
aus
|.
PHP_MSHUTDOWN_FUNCTION (wird einmal pro Prozess ausgeführt)
Anbei sind die Diagramme von Multi-Threading und Multi-Prozess
dnl bedeutet, diese Zeile auskommentieren, genau wie // in PHP. Ich werde nicht untersuchen, warum es DNL ist, ich weiß nur, dass es eine Notiz ist.
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)fi
Ich habe festgestellt, dass in vielen Lehrbüchern, die vor langer Zeit im Internet geschrieben wurden, Funktionen in der Header-Datei deklariert sind. Es scheint, dass neuere Versionen dies nicht erfordern. Weil das standardmäßig generierte Framework keine Wörter wie „PHP_FUNCTION(confirm_helloworld_compiled)“ in der Header-Datei sieht. Machen Sie sich also keine allzu großen Sorgen um diese Datei. (Es empfiehlt sich jedoch, die zu implementierende Funktion in der Header-Datei zu deklarieren.)
Beachten Sie, dass die Versionsnummer, die unter helloworld.c verwendet wird, hier definiert ist
#define PHP_HELLOWORLD_VERSION "0.1.0"
Viele Makros von PHP_XXX sind in main/php.h definiert
#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) #endif
1 Dateien (Führen Sie die erforderlichen Makros, API-Definitionen usw. ein); die Header-Datei, die das Modul
enthalten muss, ist nur eine php.h, die sich im Hauptverzeichnis befindet. Diese Datei enthält verschiedene Makros und API-Definitionen, die zum Erstellen des Moduls erforderlich sind.
2. Exportierte Funktionen deklarieren (zur Deklaration von Zend-Funktionsblöcken);
Das Makro ZEND_FUNCTION deklariert eine neue C-Funktion, die mit der internen Zend-API kompiliert wurde. Diese C-Funktion ist vom Typ void, verwendet INTERNAL_FUNCTION_PARAMETERS (dies ist ein weiteres Makro) als Parameter und dem Funktionsnamen wird zif_ vorangestellt.
PHP_FUNCTION ist dasselbe und das Makro wurde in /main/php.h definiert
#define PHP_FUNCTION ZEND_FUNCTION
3. Deklarieren Sie den Zend-Funktionsblock
Jetzt haben Sie ihn deklariert Die Funktion wird exportiert, aber Zend weiß nicht, wie sie aufgerufen werden soll, daher muss sie in Zend importiert werden. Die Einführung dieser Funktionen wird durch ein Array mit N zend_function_entry-Strukturen vervollständigt. Jedes Element im Array entspricht einer extern sichtbaren Funktion, und jedes Element enthält den Namen einer Funktion, wie er in PHP erscheint, und den im C-Code definierten Namen.
4. Deklarieren Sie das Zend-Modul.
Die Zend-Modulinformationen werden in einer Struktur namens zend_module_entry gespeichert, die alle Modulinformationen enthält, die Zend bereitgestellt werden müssen.
5. Implementieren Sie die Funktion get_module();
这个函数只用于动态可加载模块
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命令,一切恢复正常。
Das obige ist der detaillierte Inhalt vonAutomatische Generierung eines Erweiterungsframeworks für PHP-Erweiterungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!