摘要:編譯工具這個腳本主要生成了編譯需要的配置以及擴展的基本結(jié)構(gòu)這個腳本主要是獲取的安裝信息用于生成文件編寫擴展的基本步驟通過目錄下腳本生成擴展的基本框架修改配置設(shè)置編譯配置參數(shù)設(shè)置擴展的源文件依賴庫函數(shù)檢查等等定義一個這樣的編譯參數(shù)
1. 編譯工具
(a).ext_skel:這個腳本主要生成了編譯需要的配置以及擴展的基本結(jié)構(gòu)
(b).php-config:這個腳本主要是獲取PHP的安裝信息
(c).phpize:用于生成configure文件
2.編寫擴展的基本步驟
a.通過ext目錄下ext_skel腳本生成擴展的基本框架;
./ext_skel --extname=wu
b.修改config.m4配置:設(shè)置編譯配置參數(shù)、設(shè)置擴展的源文件、依賴庫/函數(shù)檢查等等;
PHP_ARG_WITH(arg_name,check message,help info): 定義一個--with-feature[=arg]這樣的編譯參數(shù),參數(shù)分別為 參數(shù)名、執(zhí)行./configure是展示信息、執(zhí)行--help時展示信息 $PHP_參數(shù)名:獲取對應(yīng)的參數(shù)值
PHP_ARG_ENABLE(arg_name,check message,help info): 定義一個--enable-feature[=arg]或--disable-feature參 數(shù),--disable-feature等價于--enable-feature=no,這個宏與PHP_ARG_WITH類似,通常情況下如果配置的參數(shù)需 要額外的arg值會使用PHP_ARG_WITH,而如果不需要arg值,只用于開關(guān)配置則會使用PHP_ARG_ENABLE。
./configure時輸出結(jié)果,其中error將會中斷configure執(zhí)行 AC_MSG_CHECKING(message) AC_MSG_RESULT(message) AC_MSG_ERROR(message)
PHP_CHECK_LIBRARY(library, function [, action-found [, action-not-found ]]): 檢查依賴的庫中是否存在需要 的function,action-found為存在時執(zhí)行的動作,action-not-found為不存在時執(zhí)行的動作
c.編寫擴展要實現(xiàn)的功能:按照PHP擴展的格式以及PHP提供的API編寫功能;
#1.注冊全局變量 //php_wu.h #define MYTEST_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(mytest, v) //定義全局變量 ZEND_BEGIN_MODULE_GLOBALS(mytest) zend_long open_cache; HashTable class_table; ZEND_END_MODULE_GLOBALS(mytest) //wu.c ZEND_DECLARE_MODULE_GLOBALS(mytest)
#2.鉤子函數(shù) PHP_MINIT_FUNCTION(mytest){ 這個階段可以進行內(nèi)部類的注冊,如果你的擴展提供 了類就可以在此函數(shù)中完成注冊;除了類還可以在此 函數(shù)中注冊擴展定義的常量 } PHP_RINIT_FUNCTION(mytest){ 如果你的擴展需要針對每一個請求進行處理則可以設(shè) 置這個函數(shù),如:對請求進行filter } PHP_RSHUTDOWN_FUNCTION(mytest){ 此函數(shù)在請求結(jié)束時被調(diào)用 } PHP_MSHUTDOWN_FUNCTION(mytest){ 模塊關(guān)閉階段回調(diào)的函數(shù),與module_startup_func對應(yīng), 此階段主要可以進行一些資源的清理 }
#3.自定義函數(shù) PHP_FUNCTION(my_func_1){ 自定義內(nèi)部函數(shù)1 } PHP_FUNCTION(my_func_1){ 自定義內(nèi)部函數(shù)2(帶參) zval *arr; //l(L)整型,L當數(shù)據(jù)溢出不報錯 //(b)布爾型,(d)浮點型 //s(S)字符串型,其中"s"將參數(shù)解析到char*,且需要額外提供一個size_t類型的變量用于獲取字符串長度,“S”為zend_string //a(A)數(shù)組型,o(O)對象型,r資源型,z任意類型 //|: 表示此后的參數(shù)為可選參數(shù),可以不傳,比如解析規(guī)則為:"al|b",則可以傳2個或3個參數(shù) //+、* : 用于可變參數(shù),+、*的區(qū)別在于 * 表示可以不傳可變參數(shù),而 + 表示可變參數(shù)至少有一個。需要額外提供一個int類型的變量用于獲取具體的數(shù)量 if(zend_parse_parameters(ZEND_NUM_ARGS(), "la", &lval, &arr) == FAILURE){ RETURN_FALSE; } } PHP_FUNCTION(my_func_3){ 自定義內(nèi)部函數(shù)3(引用傳參) zval *lval; //必須為zval zval *obj; //引用參數(shù)解析時只能使用"z"解析 if(zend_parse_parameters(ZEND_NUM_ARGS(), "zo", &lval, &obj) == FAILURE){ RETURN_FALSE; } } //參數(shù)信息(參數(shù)組名,無意義,返回值是否引用,參數(shù)個數(shù)) ZEND_BEGIN_ARG_INFO_EX(arg_info_3, 0, 0, 2) //pass_by_ref表示是否引用傳參,name為參數(shù)名稱 ZEND_ARG_INFO(pass_by_ref, name) //顯式聲明此參數(shù)的類型為指定類的對象,等價于PHP中這樣聲明:MyClass $obj ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) //顯式聲明此參數(shù)類型為數(shù)組,等價于:array $arr ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) //通用宏,自定義各個字段 ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) //聲明為可變參數(shù) ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) ZEND_END_ARG_INFO() PHP_FUNCITON(my_func_3){ 自定義內(nèi)部函數(shù)4(返回值) //返回布爾型,b:IS_FALSE、IS_TRUE RETURN_BOOL(b) //返回false RETURN_FALSE //返回true RETURN_TRUE //返回NULL RETURN_NULL() //返回整形,l類型:zend_long RETURN_LONG(l) //返回浮點值,d類型:double RETURN_DOUBLE(d) //返回字符串,內(nèi)部字符串,s類型為:zend_string * RETURN_STR(s) //返回char *類型的字符串,s類型為char * RETURN_STRING(s) //返回空字符串 RETURN_EMPTY_STRING() //返回資源,r類型:zend_resource * RETURN_RES(r) //返回數(shù)組,r類型:zend_array * RETURN_ARR(r) //返回對象,r類型:zend_object * RETURN_OBJ(r) } const zend_function_entry mytest_functions[] = { PHP_FE(my_func_1,NULL) PHP_FE(my_func_2,NULL) PHP_FE(my_func_3,arg_info_3) PHP_FE(my_func_4,NULL) PHP_FE_END //末尾必須加這個 }; zend_module_entry mytest_module_entry = { STANDARD_MODULE_HEADER, //宏統(tǒng)一設(shè)置 "mytest", //模塊名 mytest_functions, //自定義函數(shù)數(shù)組 PHP_MINIT(mytest), //擴展初始化回調(diào)函數(shù) PHP_MSHUTDOWN(mytest), //擴展關(guān)閉時回調(diào)函數(shù) PHP_RINIT(mytest), //請求開始前回調(diào)函數(shù) PHP_RSHUTDOWN(mytest), //請求結(jié)束時回調(diào)函數(shù) NULL, //PHP_MINFO(mytest),php_info展示的擴展信息處理函數(shù) "1.0.0", STANDARD_MODULE_PROPERTIES //宏統(tǒng)一設(shè)置 }; ZEND_GET_MODULE(mytest) //讀取mytest_module_entry結(jié)構(gòu)體
#4.zval操作工具類 //創(chuàng)建(這些宏第一個參數(shù)z均為要設(shè)置的zval的指針,后面為要設(shè)置的zend_value) ZVAL_UNDEF(z): 表示zval被銷毀 ZVAL_NULL(z): 設(shè)置為NULL ZVAL_FALSE(z): 設(shè)置為false ZVAL_TRUE(z): 設(shè)置為true ZVAL_BOOL(z, b): 設(shè)置為布爾型,b為IS_TRUE、IS_FALSE,與上面兩個等價 ZVAL_LONG(z, l): 設(shè)置為整形,l類型為zend_long,如:zval z; ZVAL_LONG(&z, 88); ZVAL_DOUBLE(z, d): 設(shè)置為浮點型,d類型為double ZVAL_STR(z, s): 設(shè)置字符串,將z的value設(shè)置為s,s類型為zend_string*,不會增加s的refcount ZVAL_ARR(z, a): 設(shè)置為數(shù)組,a類型為zend_array* ZVAL_OBJ(z, o): 設(shè)置為對象,o類型為zend_object* ZVAL_RES(z, r): 設(shè)置為資源,r類型為zend_resource* ZVAL_REF(z, r): 設(shè)置為引用,r類型為zend_reference* ZVAL_NEW_EMPTY_REF(z): 新創(chuàng)建一個空引用,沒有設(shè)置具體引用的value //獲取值及類型 Z_LVAL(zval)、Z_LVAL_P(zval_p): 返回zend_long Z_DVAL(zval)、Z_DVAL_P(zval_p): 返回double Z_STR(zval)、Z_STR_P(zval_p): 返回zend_string* Z_STRVAL(zval)、Z_STRVAL_P(zval_p): 返回char*,即:zend_string->val Z_STRLEN(zval)、Z_STRLEN_P(zval_p): 獲取字符串長度 Z_STRHASH(zval)、Z_STRHASH_P(zval_p): 獲取字符串的哈希值 Z_ARR(zval)、Z_ARR_P(zval_p)、Z_ARRVAL(zval)、Z_ARRVAL_P(zval_p): 返回zend_array* Z_OBJ(zval)、Z_OBJ_P(zval_p): 返回zend_object* Z_OBJCE(zval)、Z_OBJCE_P(zval_p): 返回對象的zend_class_entry* Z_OBJPROP(zval)、Z_OBJPROP_P(zval_p): 獲取對象的成員數(shù)組 Z_RES(zval)、Z_RES_P(zval_p): 返回zend_resource* Z_RES_HANDLE(zval)、Z_RES_HANDLE_P(zval_p): 返回資源handle Z_RES_TYPE(zval)、Z_RES_TYPE_P(zval_p): 返回資源type Z_RES_VAL(zval)、Z_RES_VAL_P(zval_p): 返回資源ptr Z_REF(zval)、Z_REF_P(zval_p): 返回zend_reference* Z_REFVAL(zval)、Z_REFVAL_P(zval_p): 返回引用的zval* //類型轉(zhuǎn)換 convert_to_long(zval *op); convert_to_double(zval *op); convert_to_long_base(zval *op, int base); convert_to_null(zval *op); convert_to_boolean(zval *op); convert_to_array(zval *op); convert_to_object(zval *op); zval_get_long(op):獲取格式化為long的值,返回值為zend_long zval_get_double(op):獲取格式化為double的值,返回值double zval_get_string(op):獲取格式化為string的值,返回值zend_string * //字符串操作 zend_string_init(const char *str, size_t len, int persistent);創(chuàng)建zend_string zend_string_copy(zend_string *s);字符串復(fù)制,只增加引用 zend_string_dup(zend_string *s, int persistent);字符串拷貝,硬拷貝 zend_string_realloc(zend_string *s, size_t len, int persistent);將字符串按len大小重新分配,會減少s的refcount,返回新的字符串 zend_string_extend(zend_string *s, size_t len, int persistent);延長字符串,與zend_string_realloc()類似,不同的是len不能小于s的長度 zend_string_refcount(const zend_string *s);獲取字符串refcount zend_string_addref(zend_string *s);增加字符串refcount zend_string_delref(zend_string *s);減少字符串refcount zend_string_release(zend_string *s);釋放字符串,減少refcount,為0時銷毀 zend_string_free(zend_string *s);銷毀字符串,不管引用計數(shù)是否為0 zend_string_equals(zend_string *s1, zend_string *s2);比較兩個字符串是否相等,區(qū)分大小寫 zend_string_equals_ci(s1, s2);比較兩個字符串是否相等,不區(qū)分大小寫 //數(shù)組操作 ZVAL_NEW_ARR(z): 新分配一個數(shù)組,主動分配一個zend_array zend_hash_init(Z_ARRVAL(array), size, NULL, ZVAL_PTR_DTOR, 0);初始化數(shù)組 1) key為zend_string zend_hash_update(ht, key, pData):插入或更新元素,會增加key的refcount zend_hash_add(ht, key, pData):添加元素,與zend_hash_update()類似,不同的地方在于如果元素已經(jīng)存在則不會更新 2) key為普通字符串:char* zend_hash_str_update(ht, key, len, pData) #define zend_hash_str_add(ht, key, len, pData) 3) key為數(shù)值索引 zend_hash_index_update(ht, h, pData):更新第h個元素 zend_hash_index_add(ht, h, pData):插入元素,h為數(shù)值 zend_hash_find(const HashTable *ht, zend_string *key);根據(jù)zend_string key查找數(shù)組元素 zend_hash_str_find(const HashTable *ht, const char *key, size_t len);根據(jù)普通字符串key查找元素 zend_hash_index_find(const HashTable *ht, zend_ulong h);獲取數(shù)值索引元素 zend_hash_exists(const HashTable *ht, zend_string *key);判斷元素是否存在 zend_hash_str_exists(const HashTable *ht, const char *str, size_t len);判斷元素是否存在 zend_hash_index_exists(const HashTable *ht, zend_ulong h);判斷元素是否存在 zend_hash_num_elements(ht):獲取數(shù)組元素數(shù) zend_hash_del(HashTable *ht, zend_string *key);刪除key //遍歷 ZEND_HASH_FOREACH_VAL(ht, val) { ... } ZEND_HASH_FOREACH_END(); ZEND_HASH_FOREACH_NUM_KEY(ht, _h):遍歷獲取所有的數(shù)值索引 ZEND_HASH_FOREACH_STR_KEY(ht, _key):遍歷獲取所有的key ZEND_HASH_FOREACH_KEY(ht, _h, _key):上面兩個的聚合 ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, _h, _val) :遍歷獲取數(shù)值索引key及value ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val):遍歷獲取key及valu ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val):上面兩個的聚合 zend_array_destroy(HashTable *ht):銷毀數(shù)組
#5.常量 //注冊NULL常量 REGISTER_NULL_CONSTANT(name, flags) //注冊bool常量 REGISTER_BOOL_CONSTANT(name, bval, flags) //注冊整形常量 REGISTER_LONG_CONSTANT(name, lval, flags) //注冊浮點型常量 REGISTER_DOUBLE_CONSTANT(name, dval, flags) //注冊字符串常量,str類型為char* REGISTER_STRING_CONSTANT(name, str, flags) //注冊字符串常量,截取指定長度,str類型為char* REGISTER_STRINGL_CONSTANT(name, str, len, flags)
d.生成configure:擴展編寫完成后執(zhí)行phpize腳本生成configure及其它配置文件;
phpsize
e.編譯&安裝:./configure、make、make install,然后將擴展的.so路徑添加到php.ini中。
./configure make make install
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/28580.html
摘要:引擎中定義了很多內(nèi)部函數(shù)供用戶在中使用,比如等等,除了引擎中定義的內(nèi)部函數(shù),擴展中也提供了大量內(nèi)部函數(shù),我們也可以靈活的通過擴展自行定制。頭部是一個與完全相同的結(jié)構(gòu)函數(shù)指針,展開 1.函數(shù)的存儲結(jié)構(gòu) typedef union _zend_function zend_function; union _zend_function { zend_uchar typ...
摘要:是與之間數(shù)據(jù)交換的一種協(xié)議。當收到這個請求后,會啟動對應(yīng)的程序,這里就是的解析器。接下來解析器會解析文件,初始化執(zhí)行環(huán)境,然后處理請求,再以規(guī)定規(guī)定的格式返回處理后的結(jié)果,退出進程,再把結(jié)果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數(shù)據(jù)交換的一種協(xié)議。FastCGI:同 CGI,是一種通信協(xié)議,但比 CGI 在效率上做了一些優(yōu)化。PHP-...
摘要:是與之間數(shù)據(jù)交換的一種協(xié)議。當收到這個請求后,會啟動對應(yīng)的程序,這里就是的解析器。接下來解析器會解析文件,初始化執(zhí)行環(huán)境,然后處理請求,再以規(guī)定規(guī)定的格式返回處理后的結(jié)果,退出進程,再把結(jié)果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數(shù)據(jù)交換的一種協(xié)議。FastCGI:同 CGI,是一種通信協(xié)議,但比 CGI 在效率上做了一些優(yōu)化。PHP-...
摘要:是與之間數(shù)據(jù)交換的一種協(xié)議。當收到這個請求后,會啟動對應(yīng)的程序,這里就是的解析器。接下來解析器會解析文件,初始化執(zhí)行環(huán)境,然后處理請求,再以規(guī)定規(guī)定的格式返回處理后的結(jié)果,退出進程,再把結(jié)果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數(shù)據(jù)交換的一種協(xié)議。FastCGI:同 CGI,是一種通信協(xié)議,但比 CGI 在效率上做了一些優(yōu)化。PHP-...
閱讀 810·2021-11-22 15:25
閱讀 1408·2021-09-08 09:45
閱讀 1685·2021-09-02 09:46
閱讀 1299·2019-08-30 15:56
閱讀 1528·2019-08-29 15:14
閱讀 1159·2019-08-29 13:06
閱讀 2010·2019-08-29 12:34
閱讀 1400·2019-08-26 12:14