[php-src]扩展中封装业务与 call_user_function 的使用建议
内容均以php5.6.14为例.
从一个封装 uniqid 的例子来讲。
/* {{{ wrapper of uniqid */
PHP_FUNCTION(fox)
{
// #1.
zval *prefix, *more = NULL;
zval function, *params[] = {};
// #2.
if ( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &prefix, &more) == FAILURE ) {
RETURN_FALSE;
}
params[] = prefix;
if (more) {
params[] = more;
}
// #3.
ZVAL_STRING(&function, "uniqid", );
// #4.
if ( call_user_function(EG(function_table), NULL, &function, return_value, ZEND_NUM_ARGS(), params TSRMLS_CC) == FAILURE ) {
if (return_value) {
zval_dtor(return_value);
}
zend_error(E_WARNING, "%s() calling %s() failed.", get_active_function_name(TSRMLS_C), Z_STRVAL(function));
RETURN_FALSE;
}
RETURN_STRING(Z_STRVAL_P(return_value), );
}
/* }}} */
#1.
zval 不赋值默认是非空,不要随意给 声明的 zval 赋值为 NULL,除非你知道自己在干什么,比方用在判断是否有传参;
如果你想对可选的参数使用默认值 farwish,可以像下面这样 (非用于上例):
if (more == NULL) {
MAKE_STD_ZVAL(more);
Z_STRVAL_P(more) = "farwish";
Z_STRLEN_P(more) = strlen("farwish");
Z_TYPE_P(more) = IS_STRING;
}
params[] = more;
还有别忘了 call_user_function 中的参数个数就不能再用 ZEND_NUM_ARGS(),写固定值 2 就可以了。
#2.
接收的参数类型必须用双引号包裹,为了避免其它地方也遇到这种错误,最好后面统一都用双引号。
如果接收的参数含 char *name 类型的, 别忘了要有 uint *len 跟在它后面传入。
#3. #4.
如果开头声明的是 zval *function, 并且 ZVAL_STRING 赋值 和 call_user_function 的调用都传 function, 编译能通过, 但是使用会segmentaion fault;测试证明, ZVAL_STRING 第一个参数一定是指向 zval 的地址, 而不是简单的传 zval *, 因为宏中做了 zval *__z = (z) 这么一件事, 如果 z 已经是指针, 那么值就不对了.
./Zend/zend_execute_API.c:575
int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC)
zval function_name, retval_ptr;
Thats all.
开发文档:https://github.com/farwish/php-core-hack
Link:http://www.cnblogs.com/farwish/p/5635429.html
[php-src]扩展中封装业务与 call_user_function 的使用建议的更多相关文章
- JS组件系列——在ABP中封装BootstrapTable
前言:关于ABP框架,博主关注差不多有两年了吧,一直迟迟没有尝试.一方面博主觉得像这种复杂的开发框架肯定有它的过人之处,系统的稳定性和健壮性比一般的开源框架肯定强很多,可是另一方面每每想到它繁琐的封装 ...
- 减少存储过程封装业务逻辑-web开发与传统软件开发的思维模式不同
本篇文章讨论并不是:不要使用存储过程,因为有些事情还是要存储过程来完成,不可能不用.而是关于:"业务逻辑是不是要封装在存储过程中实现,这样子php.java等就是调用存储过程". ...
- Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式
目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...
- Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载
目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...
- 直播开始:'云榨汁机'诞生记--聊聊JavaScript中的'业务建模'
闭包是JavaScript中的一个重要特性,在之前的博文中,我们说闭包是一个'看似简单,其实很有内涵'的特性.当我们用JavaScript来实现相对复杂的业务建模时,我们可以如何利用'闭包'这个特性呢 ...
- AngularJS之使用控制器封装业务逻辑
AngularJS之使用控制器封装业务逻辑 控制器的作用 我们知道,在AngularJS中,实现数据绑定的核心是scope对象.那么控制器又有什么用呢? 简单地说,没有控制器/controller,我 ...
- main.js中封装全局登录函数
1. 在 main.js 中封装全局登录函数 通过 vue 对象的原型扩展,可以扩展一个函数,这样这个函数就可以在每一个界面通过类似指向对象的方式,去访问这个函数. 如下是 main.js 扩展的函数 ...
- 示例:WPF中自定义StoryBoarService在代码中封装StoryBoard、Animation用于简化动画编写
原文:示例:WPF中自定义StoryBoarService在代码中封装StoryBoard.Animation用于简化动画编写 一.目的:通过对StoryBoard和Animation的封装来简化动画 ...
- PHP 使用 mcrypt 扩展中的 mcrypt_encrypt() 和 mcrypt_decrypt() 对数据进行加密和解密
<?php /* 使用 mcrypt 扩展中的 mcrypt_encrypt() 和 mcrypt_decrypt() 对数据进行加密和解密 */ // 加密 $algorithm = MCRY ...
随机推荐
- Image 抠图,背景透明处理
import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import javax.i ...
- 将Linux命令的结果作为下一个命令的参数
查询所有的pid并杀死. jps -l | grep bdcsc2-native-demo | awk '{print $1}' | xargs kill -9 KISS:keep it short ...
- highCharts 饼图动态加载
饼图的动态加载 (1):导入样式 <script type="text/javascript" src="<%=request.getContextPath( ...
- 转载:Scalers:要持续行动,不要自我感动
转载自微信公众号:http://mp.weixin.qq.com/s?__biz=MzA4MjIyNDYzMQ==&mid=2650846277&idx=1&sn=5d832a ...
- linux 学习2 文件处理命令
____命令格式与目录处理命令 ____目录处理命令 ____文件处理命令 ____链接命令 ls list 菜单 命令 [-选项][参数] 选项:调整功能,多个选项可以写在一起,不分顺序. 简化选项 ...
- 基本TCP套接字编程
1.listen函数 将主动套接字转换成一个被动套接字 backlog指定相应套接字连接队列的大小. 监听套接字有2个队列: (1)未完成连接队列,接收客户SYN,发出SYN.ACK,等待完成三次握手 ...
- Bloom Filter学习
参考文献: Bloom Filters - the math http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html B ...
- const的位置与区别
转自 http://www.cnblogs.com/wucx/p/4566176.html 一个比较经典的问题——问以下两种声明的区别:1) const char * p2) char * co ...
- matlab计算差分函数diff
A = 3 2 5 6 5 2 1 8 4 2 7 9 >> diff(A,1,1) ans = 2 0 -4 2 -1 0 6 1 >> diff(A,1,2) ans = ...
- Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号
www.cnblogs.com/zhangzhu/archive/2013/08/22/3274831.html 如何开启MySQL的远程帐号-1)首先以 root 帐户登陆 MySQL 在 Wind ...