PHP 內部函式不直接 return zval*,而是由 Zend 引擎預先分配 return_value 參數,擴展僅需填充該 zval。本文解析回傳值機制、ZVAL_* 與 RETVAL_* 宏家族用法。
// 錯誤示範:手動分配 zval 並 return
PHP_FUNCTION(sample_wrong) {
zval *retval;
MAKE_STD_ZVAL(retval);
ZVAL_LONG(retval, 42);
return retval; // 錯誤!引擎不接收回傳值
}
// 正確示範:填充預分配的 return_value
PHP_FUNCTION(sample_long) {
ZVAL_LONG(return_value, 42);
return; // 無需回傳值
}
// 等價於:
Z_TYPE_P(return_value) = IS_LONG;
Z_LVAL_P(return_value) = 42;
// 或直接存取:
return_value->type = IS_LONG;
return_value->value.lval = 42;
注意:return_value 的 refcount、is_ref 由引擎管理,**擴展不可直接修改**。
| 標準宏 | 簡寫宏 | 說明 |
|---|---|---|
ZVAL_LONG(zv, val) | RETVAL_LONG(val) | 整數 |
ZVAL_DOUBLE(zv, val) | RETVAL_DOUBLE(val) | 浮點數 |
ZVAL_STRING(zv, str, dup) | RETVAL_STRING(str, dup) | 字串 (dup=1 複製) |
ZVAL_STRINGL(zv, str, len, dup) | RETVAL_STRINGL(str, len, dup) | 二進制字串 |
ZVAL_BOOL(zv, val) | RETVAL_BOOL(val) | 布林 |
ZVAL_NULL(zv) | RETVAL_NULL() | NULL |
ZVAL_RESOURCE(zv, id) | RETVAL_RESOURCE(id) | 資源 ID |
ZVAL_ZVAL(dst, src, copy, dtor) | RETVAL_ZVAL(zv, copy, dtor) | 複製 zval |