php7 zval ptr dtor,php7扩展开发[9] zend_call_method和zend_call_function

params = params;

fci.no_separation = 1;

fci.symbol_table = NULL;

if (!fn_proxy && !obj_ce) {

fci.function_table = !object ? EG(function_table) : NULL;

//看这里.原来调用的是zend_call_function

//看这里.原来调用的是zend_call_function

//看这里.原来调用的是zend_call_function

result = zend_call_function(&fci, NULL);

zval_ptr_dtor(&fci.function_name);

} else {

zend_fcall_info_cache fcic;

fcic.initialized = 1;

if (!obj_ce) {

obj_ce = object ? Z_OBJCE_P(object) : NULL;

}

if (obj_ce) {

function_table = &obj_ce->function_table;

} else {

function_table = EG(function_table);

}

if (!fn_proxy || !*fn_proxy) {

if ((fcic.function_handler = zend_hash_find_ptr(function_table, Z_STR(fci.function_name))) == NULL) {

/* error at c-level */

zend_error_noreturn(E_CORE_ERROR, "Couldn‘t find implementation for method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name);

}

if (fn_proxy) {

*fn_proxy = fcic.function_handler;

}

} else {

fcic.function_handler = *fn_proxy;

}

fcic.calling_scope = obj_ce;

if (object) {

fcic.called_scope = Z_OBJCE_P(object);

} else {

zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));

if (obj_ce &&

(!called_scope ||

!instanceof_function(called_scope, obj_ce))) {

fcic.called_scope = obj_ce;

} else {

fcic.called_scope = called_scope;

}

}

fcic.object = object ? Z_OBJ_P(object) : NULL;

//看这里.原来调用的是zend_call_function

//看这里.原来调用的是zend_call_function

//看这里.原来调用的是zend_call_function

result = zend_call_function(&fci, &fcic);

zval_ptr_dtor(&fci.function_name);

}

if (result == FAILURE) {

/* error at c-level */

if (!obj_ce) {

obj_ce = object ? Z_OBJCE_P(object) : NULL;

}

if (!EG(exception)) {

zend_error_noreturn(E_CORE_ERROR, "Couldn‘t execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name);

}

}

/* copy arguments back, they might be changed by references */

if (param_count > 0 && Z_ISREF(params[0]) && !Z_ISREF_P(arg1)) {

ZVAL_COPY_VALUE(arg1, &params[0]);

}

if (param_count > 1 && Z_ISREF(params[1]) && !Z_ISREF_P(arg2)) {

ZVAL_COPY_VALUE(arg2, &params[1]);

}

if (!retval_ptr) {

zval_ptr_dtor(&retval);

return NULL;

}

return retval_ptr;

}

我们可以看到zend_call_method调用zend_call_function,函数体定义在Zend/zend_API.h下:

ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache);

我们可以看到要想使用zend_call_function 必须要了解zend_fcall_info结构体。

PHP7 中

typedef struct _zend_fcall_info {

size_t size;

HashTable *function_table;

zval function_name;

zend_array *symbol_table;

zval *retval;

zval *params;

zend_object *object;

zend_bool no_separation;

uint32_t param_count;

} zend_fcall_info;

由于网上流传的代码都是PHP5的代码,我们也就再贴一下PHP5的代码,到改造代码时,可以有个借鉴。

PHP5 中

typedef struct _zend_fcall_info {

size_t size;

HashTable *function_table;

zval *function_name;

HashTable *symbol_table;

zval **retval_ptr_ptr;

zend_uint param_count;

zval ***params;

zval *object_ptr;

zend_bool no_separation;

} zend_fcall_info;

其中有变化的参数:

zval *function_name; -> zval function_name;

zval **retval_ptr_ptr; -> zval *retval;

zval *object_ptr; -> zend_object *object;

zval ***params; -> zval *params;

在PHP7的扩展使用PHP5的代码make时,会出现如下错误:

error: incompatible types when assigning to type ‘struct zval *’ from type ‘zval’

error: ‘zend_fcall_info’ has no member named ‘object’

error: ‘zend_fcall_info’ has no member named ‘retval’

我们搜一下php源码中zend_call_function中的使用情况,我们会发现自动加载中的代码如下:

static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval *retval, int argc, zval *argv)

{

zend_function *func = pce->constructor;

zend_fcall_info fci;

zend_fcall_info_cache fcc;

zval dummy;

spl_instantiate(pce, retval);

fci.size = sizeof(zend_fcall_info);

fci.function_table = &pce->function_table;

ZVAL_STR(&fci.function_name, func->common.function_name);

fci.object = Z_OBJ_P(retval);

fci.symbol_table = NULL;

fci.retval = &dummy;

fci.param_count = argc;

fci.params = argv;

fci.no_separation = 1;

fcc.initialized = 1;

fcc.function_handler = func;

fcc.calling_scope = EG(scope);

fcc.called_scope = pce;

fcc.object = Z_OBJ_P(retval);

zend_call_function(&fci, &fcc);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值