zoukankan      html  css  js  c++  java
  • 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()
  • 相关阅读:
    CodeForces gym Nasta Rabbara lct
    bzoj 4025 二分图 lct
    CodeForces 785E Anton and Permutation
    bzoj 3669 魔法森林
    模板汇总——快读 fread
    bzoj2049 Cave 洞穴勘测 lct
    bzoj 2002 弹飞绵羊 lct裸题
    HDU 6394 Tree 分块 || lct
    HDU 6364 Ringland
    nyoj221_Tree_subsequent_traversal
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3291999.html
Copyright © 2011-2022 走看看