【问题标题】:Lua return custom data from C functionLua从C函数返回自定义数据
【发布时间】:2015-06-02 02:11:36
【问题描述】:

尽管努力搜索,但我找不到有效的 Lua C API 示例来调用从 C 函数返回自定义数据的 Lua 函数。 例如,我有注册函数“GetMyVector”,然后我从 lua 调用它以从 C 中检索信息,我得到的是一个表,但我想要的是像 C 中一样从结构访问访问变量,例如:

local x = GetMyVector()
print(x[1]) -- i 
print(x[2]) -- j
print(x[3]) -- k
-- how to access it via like this:
print(x.i)
print(x.j)
print(x.k)

我的 C 函数通过 lua_pushnumber 将向量推入 3 维数组:

static int GetMyVector(lua_State *L)
{
    vec3_t vec;
    vec[0] = 1;
    vec[1] = 2;
    vec[3] = 3;
    lua_newtable(L);
    lua_pushnumber(L, vec[0]);
    lua_rawseti(L, -2, 1);
    lua_pushnumber(L, vec[1]);
    lua_rawseti(L, -2, 2);
    lua_pushnumber(L, vec[2]);
    lua_rawseti(L, -2, 3);
    return 1;
}

【问题讨论】:

  • “如果您有任何相关的教程和信息,请在下方粘贴 lnk,我将不胜感激。” 有问题请我们推荐或查找书籍、工具、软件图书馆、教程或其他非现场资源对于 Stack Overflow 来说是无关紧要的,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,请描述问题以及迄今为止为解决该问题所做的工作。
  • 是的,我设法解决了这个问题,但老实说,我不知道该怎么做,因为我也不知道如何命名,找不到任何信息来解决这个问题.

标签: c++ c lua luabind


【解决方案1】:

你可能想要lua_settable。它允许为表设置任何键。如果键是文字,您可以通过 x["i"]x.i 获取数据。 代码应该是这样的

static int GetMyVector(lua_State *L)
{
    vec3_t vec;
    vec[0] = 1;
    vec[1] = 2;
    vec[3] = 3;
    lua_newtable(L);

    lua_pushliteral(L, "i");
    lua_pushnumber(L, vec[0]);
    lua_settable(L, -2);

    lua_pushliteral(L, "j");
    lua_pushnumber(L, vec[1]);
    lua_settable(L, -2);

    lua_pushliteral(L, "k");
    lua_pushnumber(L, vec[2]);
    lua_settable(L, -2);
    return 1;
}

【讨论】:

    【解决方案2】:

    它有点扩展,但感谢@geov,我找到了我想要的东西,它有点类似于我认为 C# 中的属性样式,这里有解决方案:

    #define MYCLASSNAME "vec"
    
    typedef struct {
        int i, j, k;
    } MyVec_t;
    
    typedef int(*Xet_func) (lua_State *L, void *v);
    
    /* member info for get and set handlers */
    typedef const struct{
        const char *name;  /* member name */
        Xet_func func;     /* get or set function for type of member */
        size_t offset;     /* offset of member within MyVec_t */
    }  Xet_reg_pre;
    
    typedef Xet_reg_pre * Xet_reg;
    
    // properties
    static int Get_Int(lua_State *L, void *v) {
        lua_pushnumber(L, *(int*)v);
        return 1;
    }
    
    static int Set_Int(lua_State *L, void *v) {
        *(int*)v = luaL_checkinteger(L, 3);
        return 0;
    }
    
    static int Get_Number(lua_State *L, void *v) {
        lua_pushnumber(L, *(lua_Number*)v);
        return 1;
    }
    
    static int Set_Number(lua_State *L, void *v) {
        *(lua_Number*)v = luaL_checknumber(L, 3);
        return 0;
    }
    
    static int Get_String(lua_State *L, void *v) {
        lua_pushstring(L, (char*)v);
        return 1;
    }
    
    static void Property_Add(lua_State *L, Xet_reg l)
    {
        for (; l->name; l++) {
            lua_pushstring(L, l->name);
            lua_pushlightuserdata(L, (void*)l);
            lua_settable(L, -3);
        }
    }
    
    static int Property_Call(lua_State *L)
    {
        Xet_reg m = (Xet_reg)lua_touserdata(L, -1);  
        lua_pop(L, 1);                               
        luaL_checktype(L, 1, LUA_TUSERDATA);
        return m->func(L, (void *)((char *)lua_touserdata(L, 1) + m->offset));
    }
    
    static int index_handler(lua_State *L)
    {
        /* stack has userdata, index */
        lua_pushvalue(L, 2);                     /* dup index */
        lua_rawget(L, lua_upvalueindex(1));      /* lookup member by name */
        if (!lua_islightuserdata(L, -1)) {
            lua_pop(L, 1);                         /* drop value */
            lua_pushvalue(L, 2);                   /* dup index */
            lua_gettable(L, lua_upvalueindex(2));  /* else try methods */
            if (lua_isnil(L, -1))                  /* invalid member */
                luaL_error(L, "cannot get member '%s'", lua_tostring(L, 2));
            return 1;
        }
        return Property_Call(L);                      /* call get function */
    }
    
    static int newindex_handler(lua_State *L)
    {
        /* stack has userdata, index, value */
        lua_pushvalue(L, 2);                     /* dup index */
        lua_rawget(L, lua_upvalueindex(1));      /* lookup member by name */
        if (!lua_islightuserdata(L, -1))         /* invalid member */
            luaL_error(L, "cannot set member '%s'", lua_tostring(L, 2));
        return Property_Call(L);                      /* call set function */
    }
    
    static MyVec_t *CheckMyVec(lua_State *L, int index) // get data
    {
        MyVec_t *p;
        luaL_checktype(L, index, LUA_TUSERDATA);
        p = (MyVec_t *)luaL_checkudata(L, index, MYCLASSNAME);
        return p;
    }
    
    static MyVec_t *PushMyVec(lua_State *L) // push data
    {
        MyVec_t *p = (MyVec_t *)lua_newuserdata(L, sizeof(MyVec_t));
        luaL_getmetatable(L, MYCLASSNAME);
        lua_setmetatable(L, -2);
        return p;
    }
    
    static int MyVec_Create(lua_State *L)   // C function which will push data
    {
        MyVec_t *p;
        p = PushMyVec(L);
        p->i = luaL_checkinteger(L, 1);
        p->j = luaL_checkinteger(L, 2);;
        p->k = luaL_checkinteger(L, 3);;
        return 1;
    }
    
    static int MyVec_destroy(lua_State *L)
    {
        MyVec_t *p = (MyVec_t *)lua_touserdata(L, 1);
        return 0;
    }
    
    static int MyVec_Position(lua_State *L)
    {
        MyVec_t *p = CheckMyVec(L, 1);
        double   x = p->i;
        double   y = p->j;
        double   z = p->k;
        if (lua_gettop(L) > 1) {
            p->i = luaL_checknumber(L, 2);
            p->j = luaL_checknumber(L, 3);
            p->k = luaL_checknumber(L, 4);
        }
        lua_pushnumber(L, x);
        lua_pushnumber(L, y);
        lua_pushnumber(L, z);
        return 2;
    }
    
    
    static const luaL_Reg myvec_meta_methods[] = {
        { "__gc", MyVec_destroy },
        { 0, 0 }
    };
    
    static const luaL_Reg myvec_methods[] = {
        { "create",  MyVec_Create },
        { "position", MyVec_Position },
        { 0, 0 }
    };
    
    static const Xet_reg_pre MyVec_get[] = {
        { "i", Get_Int, offsetof(MyVec_t, i) },
        { "j", Get_Int, offsetof(MyVec_t, j) },
        { "k", Get_Int, offsetof(MyVec_t, k) },
        { 0, 0 }
    };
    
    static const Xet_reg_pre MyVec_set[] = {
        { "i", Set_Int, offsetof(MyVec_t, i) },
        { "j", Set_Int, offsetof(MyVec_t, j) },
        { "k", Set_Int, offsetof(MyVec_t, k) },
        { 0, 0 }
    };
    
    
    int MyVec_Register(lua_State *L)
    {
        int metatable, methods;
    
        /* create methods table, & add it to the table of globals */
        luaL_openlib(L, MYCLASSNAME, myvec_methods, 0);
        methods = lua_gettop(L);
    
        /* create metatable for MyVec_t, & add it to the registry */
        luaL_newmetatable(L, MYCLASSNAME);
        luaL_openlib(L, 0, myvec_meta_methods, 0);  /* fill metatable */
        metatable = lua_gettop(L);
    
        lua_pushliteral(L, "__metatable");
        lua_pushvalue(L, methods);              /* dup methods table*/
        lua_rawset(L, metatable);               /* hide metatable:
                                                metatable.__metatable = methods */
        lua_pushliteral(L, "__index");
        lua_pushvalue(L, metatable);            /* upvalue index 1 */
        Property_Add(L, MyVec_get);             /* fill metatable with getters */
        lua_pushvalue(L, methods);              /* upvalue index 2 */
        lua_pushcclosure(L, index_handler, 2);
        lua_rawset(L, metatable);               /* metatable.__index = index_handler */
    
        lua_pushliteral(L, "__newindex");
        lua_newtable(L);                        /* table for members you can set */
        Property_Add(L, MyVec_set);             /* fill with setters */
        lua_pushcclosure(L, newindex_handler, 1);
        lua_rawset(L, metatable);               /* metatable.__newindex = newindex_handler */
    
        lua_pop(L, 1);                          /* drop metatable */
        return 1;                               /* return methods on the stack */
    }
    

    【讨论】:

      猜你喜欢
      • 2016-04-15
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2013-09-02
      • 2011-10-05
      相关资源
      最近更新 更多