作者: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函数的两种方法的更多相关文章

  1. C++ DLL导出函数的两种方法(导出序号那种方法,别人看不到函数名)

    第一种就直接导出函数名如下代码: #ifdef__cplusplus #define TEXPORT extern "c" _declspec(dllexport) #dlse # ...

  2. (查找函数+atoi)判断与(注册函数+strcmp函数)判断两种方法

    loadrunner中接口判断的2中方法    如下: 1. ●查找函数web_reg_find() ● atoi():将字符串转换为整型值 作比较  > 0 Action() { //检查点函 ...

  3. C#子类重写父类函数的两种方法

    (1)使用Virtual关键字Override从写 父类子类代码如下,不能修改public 为其它权限 public virtual void Clear() { UpdateView(); } pu ...

  4. Nodejs回调加超时限制两种实现方法

    odejs回调加超时限制两种实现方法 Nodejs下的IO操作都是异步的,有时候异步请求返回太慢,不想无限等待回调怎么办呢?我们可以给回调函数加一个超时限制,到一定时间还没有回调就表示失败,继续后面的 ...

  5. Linux上安装Perl模块的两种方法

    Linux/Unix下安装Perl模块有两种方法:手工安装和自动安装.第一种方法是从CPAN上下载  您需要的模块,手工编译.安装.第二种方法是联上internet,使用一个叫做CPAN的模块自动完 ...

  6. (转)DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件)http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792 ...

  7. 【转】DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...

  8. JavaScript 函数的两种声明方式

    1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...

  9. JavaScript两种方法来定义一个函数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. 解决Ubuntu DNS解析慢、上网速度慢

    自从ubuntu升级到10.04后,上网速度感觉变慢了很多(ADSL),原因也众说分云,有说是firefox浏览器造成的,于是用chrome访问,速度依然很慢,可见不是由于浏览器造成的. 网速慢, 是 ...

  2. VueJS搭建简单后台管理系统框架(一)环境搭建

    做这份笔记的时候,Vue.js还是1.0,10月份Vue已经升级到2.0,这边也进行相应的更新,用Vue2.0进行一个简单的环境搭建 饿了么也刚好开源了其基于Vue.js的UI框架element-ui ...

  3. Arduino当avr开发板

    原理并不复杂,因为arduino本来就是avr+一堆的库,找个能编译出hex的工具下载到板子就行. 但实际做起来还是碰到很多问题. 先是尝试eclipse+avr plugin 编译时出现make: ...

  4. JSP中的Attribute和InitParameter

    属性:Attribute类型:应用/上下文,请求,会话(ServletContext,HttpServletRequest/ServletRequest,HttpSession)设置方法:setAtt ...

  5. 车间任务不允许"每个装配件"超过100000

    应用 Oracle Work in   Progress 层 Level Function 函数名 Funcgtion Name WIP_WIPMRMDF 表单名 Form Name WIPMRMDF ...

  6. COB (Chip On Board) 製程介紹/簡介/注意事項 II

    銀膠 (Silver glue) 如果晶圓有接地或是散熱需求時,一般都會採用[銀膠],如果沒有的話則會採用[厭氧膠].[厭氧膠]顧名思義就是阻隔它與空氣接觸後就會自然固化,不需要高溫烘烤.使用銀膠則需 ...

  7. 指定html内容下载为word文档

    解决思路是:获取html内容并传到后台,后台把html内容转换为输入流再传给浏览器,浏览器直接下载 1.获取html内容并传到后台 $("#zxjdck .ad-xzzy-anniu&quo ...

  8. Address already in use: JVM_Bind <null>:8080

    解决方法: 1重开eclipse,端口号被占用,或者杀掉进程

  9. CodeForces - 61E Enemy is weak

    Description The Romans have attacked again. This time they are much more than the Persians but Shapu ...

  10. drupal7中CKEditor开启上传图片功能

    在drupal建站中,所见即所得编辑器提供了友好的界面.也提高开发效率,而CKEditor是一款非常不错的编辑器.定制性相当高,在这推荐给大家. CKEditor和其它模块(IMCE)搭配下在文字排版 ...