我覺的對於PHP開發人員來講,學的東西很是雜,也很是多,固然了開發PHP擴展也是一個必需要掌握的技能,這裏膜拜下大神鳥哥(Laruence)~
今天要開發的第一個有點功能的擴展,主要做用是記錄日誌的時候生成日誌前面的日期部分php
#即便當前的時間,年-月-日 時:分:秒 時間戳.微妙數 [2015-05-19 20:39:32 1432039172.968199]
1. 進入php源碼src/ext目錄下面 2. 運行./ext_skel --extname=mytest 3. 進入src/ext/mytest/目錄 4. 在編寫擴展的時候要先修改下config.me文件的10-12行,去掉前面的dnl註釋,這個網上一搜一大把。
PHP_FUNCTION(get_log_title); #PHP_FUNCTION是PHP內核中聲明的一個宏 #define PHP_FUNCTION ZEND_FUNCTION //在文件src/main/php.h : 347行 #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) //文件src/Zend/zend_API.h : 68行 #define ZEND_FN(name) zif_##name //文件src/Zend/zend_API.h : 65行 #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) //文件src/Zend/zend_API.h : 67行 #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC //src/Zend/zend.h : 290行
上面的聲明函數宏展開後是:函數
void zif_get_log_title( int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)
const zend_function_entry logs_functions[] = { PHP_FE(confirm_logs_compiled, NULL) /* For testing, remove later. */ PHP_FE(get_log_title, NULL) PHP_FE_END /* Must be the last line in logs_functions[] */ }; #編寫函數 PHP_FUNCTION(get_log_title) { struct timeval tv; time_t rawtime; struct tm *timeinfo; char *formatinfo; time(&rawtime); timeinfo = localtime(&rawtime); gettimeofday(&tv, NULL); spprintf(&formatinfo, 0, "[%4d-%02d-%02d %d:%d:%d %d.%d]", 1900 + timeinfo->tm_year, 1 + timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, tv.tv_sec, tv.tv_usec); RETURN_STRING(formatinfo, 1); }
這裏還要看個宏RETURN_STRING測試
#define RETURN_STRING(s, duplicate) { RETVAL_STRING(s, duplicate); return; } //文件src/Zend/zend_API.h : 635行 #define RETVAL_STRING(s, duplicate) ZVAL_STRING(return_value, s, duplicate) //文件src/Zend/zend_API.h : 623行 #define ZVAL_STRING(z, s, duplicate) do { \ //文件src/Zend/zend_API.h : 577-583行,這個的做用實際上是給一個string類型zval變量賦值 const char *__s=(s); \ zval *__z = (z); \ Z_STRLEN_P(__z) = strlen(__s); \ //設置zval字符串長度 Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ //設置zval字符串的值 Z_TYPE_P(__z) = IS_STRING; \ //設置zval字符串的類型爲字符串 } while (0)
所以,RETURN_STRING(formatinfo, 1)展開後爲:this
do { const char *__s=(formatinfo); zval *__z = (return_value); //這裏面的return_value估計是內核定義的,相似 zval *return_value; (*__z).value.str.len = strlrn(__s); //等價於__z->value.str.len (*__z).value.str.val = (1?estrndup(__s, (*__z).value.str.len):(char*)__s); (*__z).type = 6; }
編譯的時候須要安裝好的php,好比個人php安裝在/usr/local/php/目錄下面 cd mytest; //今日剛纔編寫的函數擴展目錄 /usr/local/php/bin/phpize //運行phpize,生成configure文件 ./configure --with-php-config=/usr/local/php/bin/php-config //configure,後面的--with-php-config會生成so文件到安裝好的擴展目錄,固然也能夠不用加,聲稱以後手動copy過去 make //有錯誤的話修正 make install //運行以後會提示相似下面的內容 #Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/ #修改配置文件php.ini添加extension = mytest.so #測試 php -r 'var_dump(log_get_title());'
輸出下面內容的話,恭喜你成功了debug
[root@iforever logs]# php -r 'var_dump(get_log_title());' && date string(39) "[2015-05-19 22:52:29 1432047149.755613]" 2015年 05月 19日 星期二 22:52:29 CST
5/19/2015 10:54:38 PM日誌
本文版權歸做者iforever(luluyrt@163.com)全部,未經做者本人贊成禁止任何形式的轉載,轉載文章以後必須在文章頁面明顯位置給出做者和原文鏈接,不然保留追究法律責任的權利。code