C模块回调Lua函数的两种方法
作者:ani_di
版权所有,转载务必保留此链接 http://blog.csdn.net/ani_di
C模块回调Lua函数的两种方法
lua和C通过虚拟栈这种交互方式简单而又可靠,缺点就是C做栈平衡稍微会多写一点代码。 今天分享学到的C模块回调Lua函数的两种方法,都是炒冷饭,大侠勿喷。
1. C保存函数对象
C模块可以通过注册表保存Lua里面的对象,等适当时候取出再调用即可。
static int lua_callback = LUA_REFNIL;
static int setnotify(lua_State *L)
{
lua_callback = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
static int testnotify(lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_callback);
lua_call(L, 0, 0);
}
luaL_ref把栈顶的值取出,放到指定的tabel中,然后返回一个索引(目测是数组的index)。 lua_rawgeti把之前保存的function对象取出,再由lua_call调用。
function callback( )
print "Callback"
end
cb.setnotify(callback)
cb.testnotify()
2. C访问Lua全局环境
第二种方法更简便,C直接调用Lua中的函数,就像Lua调用C一样
static int testenv(lua_State *L)
{
lua_getglobal(L, "defcallback");
lua_call(L, 0, 0);
}
该方法的缺点就是如果C模块独立编写,方法名就不太灵活。 用这种方法一般会在Lua端再封装一层,以隔离全局环境。
3. 完整例子
cb.c
#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
static int lua_callback = LUA_REFNIL;
static int setnotify(lua_State *L)
{
lua_callback = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
static int testnotify(lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_callback);
lua_call(L, 0, 0);
}
static int testenv(lua_State *L)
{
lua_getglobal(L, "defcallback");
lua_call(L, 0, 0);
}
static const luaL_Reg cblib[] = {
{"setnotify", setnotify},
{"testnotify", testnotify},
{"testenv", testenv},
{NULL, NULL}
};
int luaopen_cb(lua_State *L)
{
luaL_register(L, "cb", cblib);
return 1;
}
test.lua
require("cb")
function callback( )
print "Callback"
end
function defcallback()
print "Predef callback"
end
cb.setnotify(callback)
cb.testnotify()
print "Done"
cb.testenv()
C模块回调Lua函数的两种方法的更多相关文章
- C++ DLL导出函数的两种方法(导出序号那种方法,别人看不到函数名)
第一种就直接导出函数名如下代码: #ifdef__cplusplus #define TEXPORT extern "c" _declspec(dllexport) #dlse # ...
- (查找函数+atoi)判断与(注册函数+strcmp函数)判断两种方法
loadrunner中接口判断的2中方法 如下: 1. ●查找函数web_reg_find() ● atoi():将字符串转换为整型值 作比较 > 0 Action() { //检查点函 ...
- C#子类重写父类函数的两种方法
(1)使用Virtual关键字Override从写 父类子类代码如下,不能修改public 为其它权限 public virtual void Clear() { UpdateView(); } pu ...
- Nodejs回调加超时限制两种实现方法
odejs回调加超时限制两种实现方法 Nodejs下的IO操作都是异步的,有时候异步请求返回太慢,不想无限等待回调怎么办呢?我们可以给回调函数加一个超时限制,到一定时间还没有回调就表示失败,继续后面的 ...
- Linux上安装Perl模块的两种方法
Linux/Unix下安装Perl模块有两种方法:手工安装和自动安装.第一种方法是从CPAN上下载 您需要的模块,手工编译.安装.第二种方法是联上internet,使用一个叫做CPAN的模块自动完 ...
- (转)DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件)http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792 ...
- 【转】DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...
- JavaScript 函数的两种声明方式
1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...
- JavaScript两种方法来定义一个函数
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- Android 常用代码片小结
1. dp px 相互转换---------------public class DensityUtil { /** * 根据手机的分辨率从 dip 的单位 转成为 px(像素) */ public ...
- 初识JavaScript,感觉整个人都不好了。。。
学习web前端的开发已经将近一个月了,开发中的三个大兄弟——“html”.“css”.“JavaScript”,小哥我已经深入接触了前两位,并与他俩建立的深厚的友谊.在编写过程中,不能说达到各位大神的 ...
- ajax完成list无刷新返回
ajax完成list无刷新返回 ajax无刷新技术总结,以下是一段我写的ajax应用的js脚本.其中提交的data刚开始我采用的是$('#formId').serialize();但是出现乱码问题,为 ...
- avalon.js实践 svg地图配置工具
MVVM模式,在很多复杂交互逻辑下面,有很大的优势.现在相关的框架也很多,现在项目中使用了avalon.js,选择它的原因,是兼容性的考虑,当然也要支持下国内开发大牛,至于性能方面的,没有实际测试过, ...
- Zend Studio错误总结
1.在升级了wampserver之后,用zendstudio发现很多地方都出错了,这时候一般先要project-clean一下,然后到run 和 debug的configuration里面把除了stu ...
- vs2013 MVC 无法确定要使用哪一版本的 ASP.NET Web Pages错误
在web.config文件<configuration>节点下添加 <appSettings> <add key="webPages:Version&q ...
- UltraISO制作U盘系统安装盘(图文教程)
虽然现在的系统盘做的越来越傻瓜化,安装方法也非常多,但是仍然时常有朋友询问怎么安装系统,特别是没有刻录机或不想刻盘,又不懂硬盘安装的朋友,这里特别介绍一种用U盘来安装系统的方法,非量产,量产因U盘芯片 ...
- delphi 关于命名
请告别 TMyXXX 的命名方法吧... 程序名: Demo.exe 窗体:TFrmDemo ,窗体文件 uFrmDemo.Pas DataModule: TDMDemo, 窗体文件 uDMDemo. ...
- python <tab>自动补全
1.获取python目录[我使用的是64位ubuntu系统] [~$]python Python 2.7.3 (default, Apr 10 2013, 06:20:15) [GCC 4.6.3] ...
- 一步一步学c#(四):继承
继承 1·继承的类型 在面向对象的编程中,有两种截然不同的继承类型,实现继承和接口继承. 实现继承:表示一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数. 接口继承:表示一个类型只继承了函 ...