擴展函式接收參數核心 API:zend_parse_parameters()。本文詳細解析格式字串、型別對應 C 資料型別、自動轉換規則、可選參數與錯誤處理模式。
函式原型
int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...);
num_args:通常傳 ZEND_NUM_ARGS()(實際傳入參數數)。
TSRMLS_DC:執行緒安全宏(ZTS 環境必需)。
type_spec:格式字串,描述期望參數型別與屬性。
...:對應型別的 C 變數位址(輸出參數)。
基礎型別格式字元對照表
| 字元 | PHP 型別 | C 變數型別 | 說明 |
l | Integer | long * | 有號長整數 |
d | Float/Double | double * | 雙精度浮點數 |
s | String | char **, int * | 字串指標 + 長度 (二進制安全) |
b | Boolean | zend_bool * | 布林值 (0/1) |
r | Resource | zval ** | 資源 zval 指標 |
a | Array | zval ** | 陣列 zval 指標 |
o | Object | zval ** | 物件 zval 指標 |
O | Object (指定類別) | zval **, zend_class_entry * | 需指定 ce |
z | 任意型別 (zval) | zval ** | 不轉換,直接取得 zval |
Z | 任意型別 (分離 zval) | zval ** | 分離副本,可安全修改 |
修飾字元
| 字元 | 位置 | 含義 |
| | 格式字串中間 | 後續參數為**可選** |
/ | 型別字元前 | 強制**分離** zval (SEPARATE_ZVAL),避免修改影響呼叫端 |
! | 型別字元前 | 允許 NULL 傳入,C 變數將設為 NULL |
實戰範例
1. 單一必要整數參數
PHP_FUNCTION(sample_getlong) {
long num;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num) == FAILURE) {
RETURN_NULL();
}
php_printf("Received integer: %ld\n", num);
RETURN_TRUE;
}
2. 字串 + 可選整數參數
PHP_FUNCTION(sample_greet) {
char *name;
int name_len;
long times = 1; // 預設值
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &name, &name_len, ×) == FAILURE) {
RETURN_NULL();
}
for (long i = 0; i < times; i++) {
php_printf("Hello, %s!\n", name);
}
RETURN_TRUE;
}
3. 允許 NULL 的資源參數
PHP_FUNCTION(sample_process_resource) {
zval *res = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r!", &res) == FAILURE) {
RETURN_NULL();
}
if (res == NULL) {
php_printf("No resource provided\n");
} else {
// 處理資源
}
RETURN_TRUE;
}
型別自動轉換規則
- 呼叫端傳入
123 (Integer),格式 "d" → 自動轉為 123.0 (double)。
- 呼叫端傳入
"456" (String),格式 "l" → 自動轉為 456 (long)。
- 呼叫端傳入
1.5 (Float),格式 "l" → 截斷為 1 (long)。
- 無法轉換(如
array 轉 long)→ 返回 FAILURE,拋出 Warning。
重要型別對應表(嚴格遵守)
| PHP 型別 | 格式字元 | C 型別 | 注意 |
| Integer | l | long * | 非 int*,64 位平台長度不同 |
| Float | d | double * | 非 float* |
| String | s | char **, int * | 需兩個參數:指標+長度 |
| Boolean | b | zend_bool * | typedef unsigned char |
| Array | a | zval ** | 操作需用 HashTable API |
| Object | o/O | zval ** | O 需額外傳 ce |
錯誤處理模式
if (zend_parse_parameters(...) == FAILURE) {
// 參數不匹配,引擎已拋出 Warning
RETURN_NULL(); // 或 RETURN_FALSE,視語意而定
}
// 參數解析成功,繼續業務邏輯
原則:解析失敗時**直接返回**,不要繼續執行後續邏輯。