文章目錄
- 一 zend_parse_parameters原型
- 二 記憶體管理
- 三 PHP函數中傳回值
一 zend_parse_parameters原型
int zend_parse_parameters ( int num_args TSRMLS_DC, char* type_spec, ... );
第一個參數是傳遞給函數的參數個數,通常的做法是傳給它ZEND_NUM_ARGS()。這是一個表示傳遞給函數參數總個數的宏。
第二個參數是為了安全執行緒,總是傳遞TSRMLS_CC宏。
第三個參數是一個字串,指定了函數期望的參數類型。
第四個參數緊跟著需要隨參數值更新的變數列表。因為PHP採用鬆散的變數定義和動態類型判斷,這樣做就使得把不同類型的參數轉化為期望的類型成為可能。
型。我們從完整性考慮也列出了一些沒有討論到的類型。
下表列出了可能指定的類型。
類型指定符 |
對應的C類型 |
描述 |
l |
long |
符號整數 |
d |
double |
浮點數 |
s |
char *, int |
二進位字串,長度 |
b |
zend_bool |
邏輯型(1或0) |
r |
zval * |
資源(檔案指標,資料庫連接等) |
a |
zval * |
聯合數組 |
o |
zval * |
任何類型的對象 |
O |
zval * |
指定類型的對象。需要提供目標對象的類類型 |
z |
zval * |
任何操作的zval |
zval是Zend引擎的值容器[1]。無論這個變數是布爾型,字串型或者其他任何類型,其資訊總會包含在一個zval聯合體中。本章中我們不直接存取zval,而是通過一些附加的宏來操作。下面的是或多或少在C中的zval, 以便我們能更好地理解接下來的代碼。
typedef union _zval {long lval;double dval;struct { char *val; int len;} str;HashTable *ht;zend_object_value obj;} zval;if (zend_parse_parameters(argc TSRMLS_CC, "sl", &str, &str_len, &n) == FAILURE) return;
注意到自動產生的程式碼會檢測函數的傳回值FAILUER(成功即SUCCESS)來判斷是否成功。如果沒有成功則立即返回,並且由zend_parse_parameters()負責觸發警告資訊。因為函數打算接收一個字串l和一個整數n,所以指定 ”sl” 作為其類型指示符。s需要兩個參數,所以我們傳遞參考char * 和 int (str 和 str_len)給zend_parse_parameters()函數。
二 記憶體管理
用於從堆中分配記憶體的PHP API幾乎和標準C API一樣。在編寫擴充的時候,使用下面與C對應(因此不必再解釋)的API函數:
emalloc(size_t size);
efree(void *ptr);
ecalloc(size_t nmemb, size_t size);
erealloc(void *ptr, size_t size);
estrdup(const char *s);
estrndup(const char *s, unsigned int length);
建議使用這些記憶體配置函數。這些函數的優點是:任何分配的記憶體在偶然情況下如果沒有被釋放,則會在頁面請求的最後被釋放。因此,真正的記憶體流失不會產生。還有一個重要的原因,你不需要檢查這些記憶體配置函數的傳回值是否為null。當記憶體配置失敗,它們會發出E_ERROR錯誤,從而決不會返回到擴充。
三 PHP函數中傳回值
擴充API包含豐富的用於從函數中傳回值的宏。這些宏有兩種主要風格:第一種是RETVAL_type()形式,它設定了傳回值但C代碼繼續執行。這通常使用在把控制交給指令碼引擎前還希望做的一些清理工作的時候使用,然後再使用C的返回聲明 ”return” 返回到PHP;後一個宏更加普遍,其形式是 RETURN_type(),他設定了傳回型別,同時返回控制到PHP。
設定傳回值並且結束函數 |
設定傳回值 |
宏傳回型別和參數 |
RETURN_LONG(l) |
RETVAL_LONG(l) |
整數 |
RETURN_BOOL(b) |
RETVAL_BOOL(b) |
布爾數(1或0) |
RETURN_NULL() |
RETVAL_NULL() |
NULL |
RETURN_DOUBLE(d) |
RETVAL_DOUBLE(d) |
浮點數 |
RETURN_STRING(s, dup) |
RETVAL_STRING(s, dup) |
字串。如果dup為1,引擎會調用estrdup()重複s,使用拷貝。如果dup為0,就使用s |
RETURN_STRINGL(s, l, dup) |
RETVAL_STRINGL(s, l, dup) |
長度為l的字串值。與上一個宏一樣,但因為s的長度被指定,所以速度更快。 |
ETURN_TRUE |
RETVAL_TRUE |
返回布爾值true。注意到這個宏沒有括弧。 |
RETURN_FALSE |
RETVAL_FALSE |
返回布爾值false。注意到這個宏沒有括弧。 |
RETURN_RESOURCE(r) |
RETVAL_RESOURCE(r) |
資源控制代碼。 |