php zend引擎api接口:ZENDAPI阅读,反射调用示例

php zend 反射 api 编程技术
发布日期 2023-06-07 更新日期 2023-06-07 阅读次数 123 文章字数 1.9k

ZENDAPI是zend引擎封装的api,方便C语言调用,在开发php扩展时非常有用。

查看ZENDAPI接口

下载php源码,在github克隆一份php-src源码即可【注意切换分支到所需版本】

在根目录/zend/zend_API.h中,定义了大量的宏,这些宏可以直接在任意地方调用而无需引入头文件。

以调用php反射调用函数示例,调用指定名称的php函数call_user_function

查阅zend_API.h可以看到如下内容:

ZEND_API zend_result _call_user_function_impl(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], HashTable *named_params);

#define call_user_function(function_table, object, function_name, retval_ptr, param_count, params) 
	_call_user_function_impl(object, function_name, retval_ptr, param_count, params, NULL)

#define call_user_function_named(function_table, object, function_name, retval_ptr, param_count, params, named_params) 
	_call_user_function_impl(object, function_name, retval_ptr, param_count, params, named_params)

参数分析:

根据经验,function_table一般是CG(function_table)或者EG(function_table),

object表示对象,如果只是普通函数则该参数传递NULL,否则传递指定的zend_object

function_name表示参数名,是zval *类型

retval_ptr表示zval *类型的指针,表示返回值引用

param_count表示参数数量

params则表示zval数组

调用var_dump示例:

{
    //函数名
    zval funName;
    ZVAL_STRING(&funName, "var_dump");  //函数名是一个callable,可以是字符串或者数组,这里是字符串,例如myClass::test等方式也支持
    
    //返回值
    zval retVal;
    
    //构造参数数组
    zval params[2];
    ZVAL_LONG(&params[0],100);
    ZVAL_STRING(&params[1], "字符串");
    
    //反射调用函数
    call_user_function(EG(function_table),NULL,&funName,&retVal,2,params);
}

相当于php代码:var_dump(100,"字符串");

反射调用对象示例

前面举例了一个反射调用var_dump,这里再举例一个反射调用对象静态方法、实例方法

php代码:

<?php
    function returnData(){
        return DB::sql("select * from user")->selectArrList();
    }

C扩展里,并没有这种链式结构,所以第一次先反射静态方法DB::sql得到DB对象,然后用db->selectArrList(),C代码如下:

{
    //函数名 ["DB","sql"]
    zval funName;
    array_init(&funName);
    add_next_index_string(&funName,"DB");
    add_next_index_string(&funName,"sql");
    
    //返回值
    zval dbObj;
    
    //构造参数数组
    zval params[1];
    ZVAL_STRING(&params[0], "select * from `user`");
    
    //反射调用静态函数
    call_user_function(EG(function_table),NULL,&funName,&dbObj,1,params);
    
    // php_var_dump(&dbObj,0);
    //根据object,再次调用selectArrList()参数
    zval funName2;
    array_init(&funName2);
    add_next_index_zval(&funName2,&dbObj);
    add_next_index_string(&funName2,"selectArrList");
    zval retDataArr;
    //反射调用实例函数
    call_user_function(EG(function_table),NULL,&funName2,&retDataArr,0,NULL);
    
    RETURN_ARR(Z_ARR_P(&retDataArr));
}

 


文章作者: 朱丰华

文章链接: https://smart.52dixiaowo.com/blog/post-430.html

版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。

php zend 反射 api

发表评论

相关推荐
朱丰华   |   7个月前   |   php

php判断是否被iframe

221    评论    点赞
朱丰华   |   1年前   |   php

php正则表达式定界符:异常Delimiter must not be alphanumeric or backslash

190    评论    点赞
朱丰华   |   1年前   |   php · 缓存 · opcache

php 加速、提高并发opcache

198    评论    点赞
朱丰华   |   1年前   |   正则 · 表达

正则表达式,实现if...then...else

112    评论    点赞
朱丰华   |   1年前   |   sql · php

PHP如何使用PDO批量执行SQL?

114    评论    点赞
朱丰华   |   1年前   |   php · 字符 · 字符串

如何在 PHP 中将字符串的第一个字母转换为大写

148    评论    点赞
朱丰华   |   1年前   |   php · 字符 · 正则

php正则表达式原生字符

85    评论    点赞
朱丰华   |   1年前   |   字符 · php · 比较

PHP比较字符串大小相关函数

110    评论    点赞
朱丰华   |   1年前   |   php

windows下编写、编译php扩展

157    评论    点赞
朱丰华   |   1年前   |   linux · php

linux下编写、编译php扩展

150    评论    点赞
朱丰华   |   1年前   |   php · 混淆 · obfuscate · git

yakpro-po混淆php代码

105    评论    点赞
朱丰华   |   1年前   |   php

php扩展编译nts的方法

85    评论    点赞
朱丰华   |   1年前   |   linux · 变量 · 环境

linux查看环境变量、设置环境变量

93    评论    点赞
朱丰华   |   1年前   |   js · php · 字符 · 字符串

php json_encode对字符串转义用法

134    评论    点赞
朱丰华   |   1年前   |   php · 捕获

php Fatal error怎么捕获

126    评论    点赞
朱丰华   |   1年前   |   php · 编译

ubuntu、centos系统从源码编译指定版本php--超详细

158    评论    点赞
朱丰华   |   1年前   |   php · git · 编译

从源码编译php

134    评论    点赞
朱丰华   |   1年前   |   php · 引用 · 变量 · c语言

php扩展内存管理与引用计数

127    评论    点赞
朱丰华   |   1年前   |   zend · php · 类型 · zval

php内核zval类型,与基本类型的转换

115    评论    点赞
朱丰华   |   1年前   |   php · zend · 调用 · 文件

php扩展开发,调用php函数

99    评论    点赞
{{item.author_name}}   |   {{new Date(item.date*1000).log()}}   |   {{it}} ·

{{item.title}}

{{item.uv}}    评论    点赞