## 前言
在這篇文章中我們將演示如何在擴展中調用函數,和調用對象的方法。代碼示例如下:
```
<?php
class demo {
public function get_site_name ($prefix) {
return $prefix."信海龍的博客\n";
}
}
function get_site_url ($prefix) {
return $prefix."www.bo56.com\n";
}
function call_function ($obj, $fun, $param) {
if ($obj == null) {
$result = $fun($param);
} else {
$result = $obj->$fun($param);
}
return $result;
}
$demo = new demo();
echo call_function($demo, "get_site_name", "site name:");
echo call_function(null, "get_site_url", "site url:");
?>
```
我們將要使用擴展實現`call_function`方法的功能。
## 代碼
### 基礎代碼
這個擴展,我們將在say擴展上增加call_function()。say擴展相關代碼大家請看這篇博文。PHP7擴展開發之hello word 文中已經詳細介紹了如何創建一個擴展和提供了源碼下載。
### 代碼實現
call_function的源碼如下:
```c
PHP_FUNCTION(call_function)
{
zval *obj = NULL;
zval *fun = NULL;
zval *param = NULL;
zval retval;
zval args[1];
#ifndef FAST_ZPP
/* Get function parameters and do error-checking. */
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz", &obj, &fun, ¶m) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_ZVAL(obj)
Z_PARAM_ZVAL(fun)
Z_PARAM_ZVAL(param)
ZEND_PARSE_PARAMETERS_END();
#endif
args[0] = *param;
if (obj == NULL || Z_TYPE_P(obj) == IS_NULL) {
call_user_function_ex(EG(function_table), NULL, fun, &retval, 1, args, 0, NULL);
} else {
call_user_function_ex(EG(function_table), obj, fun, &retval, 1, args, 0, NULL);
}
RETURN_ZVAL(&retval, 0, 1);
}
```
### 代碼解讀
參數的接受之前有過文章詳細說明過,這里就不再說了。這次我們主要說下call_user_function_ex方法的使用。
`call_user_function_ex`方法用于調用函數和方法。參數說明如下:
* 第一個參數:方法表。通常情況下,寫 EG(function_table) 更多信息查看 http://www.bo56.com/php7%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8Bcg%E5%92%8Ceg/
* 第二個參數:對象。如果不是調用對象的方法,而是調用函數,填寫NULL
* 第三個參數:方法名。
* 第四個參數:返回值。
* 第五個參數:參數個數。
* 第六個參數:參數值。是一個zval數組。
* 第七個參數:參數是否進行分離操作。詳細的,你可以搜索下 PHP 參數分離。查看相關文章
* 第八個參數:符號表。一般情況寫設置為NULL即可。