一 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) |
資源句柄。 |