将任意结构体从C传递到LUA并访问它

我遇到的问题涉及两个部分:

1.将任意结构体从C传递到Lua函数。以这两个结构体为例:

struct Person{
  int age;
  char *name;
};

struct Paper{
  int width;
  int height;
  char *color;
};

我想要通过一个简单的C函数将它们传递给Lua,比如:

template<class T>
void call(T t){
   ...  (伪代码)

  检查t:
     如果是Person,lua_getglobal(L,"sendPerson")
     如果是Paper,lua_getglobal(L,"sendPaper")

  针对t中的每个元素,检查它的类型
     如果是整数,lua_pushinteger(...)
     如果是char *,lua_pushstring(...)
  ...

  lua_pcall(...)
}

Person p = {33,"David"};
Paper A4 = {210,297,"white"};
call(p);
call(A4);

2)访问它。在Lua中,如何通过它们的名称访问这些变量?

function sendPerson(p)
    print(p.age)
    print(p.name)
end

function sendPaper(p)
    print(p.width)
    print(p.height)
    print(p.color)
end

我知道我可以使用setfield,但是除非我能够在调用Lua函数的通用方法内调用它,否则我不知道这样是否可行。

更新:这是代码。例如,下面是WM_LBUTTONDOWN事件。以这种方式,我需要为每个处理的我发送到Lua的消息制定2个方法和1个结构体:第一个方法用于创建线程,第二个方法用于调用Lua函数,还需要结构体以便将其作为参数传递给线程函数。

struct LButtonEvent{
int x,y,k;
};

LuaScript *L = new LuaScript(FILENAME);

void _onLButtonDown(LPVOID arg)
{
    LButtonEvent *b = (LButtonEvent*) arg;
    lua_State *l = L->getState();
    lua_getglobal(l,"onLButtonDown");
    lua_newtable(l);
    lua_pushinteger(l,b->x);lua_setfield(l,-2,"x");
    lua_pushinteger(l,b->y);lua_setfield(l,-2,"y");
    lua_pushinteger(l,b->k);lua_setfield(l,-2,"k");

    lua_pcall(l,1,0,0);
}

void LuaScript::onLButtonDown(LButtonEvent b)
{
    //我希望窗口继续处理消息。如果Lua脚本调用"sleep",则窗口会停止响应。
    CreateThread(0,0,(LPTHREAD_START_ROUTINE)_onLButtonDown,(LPVOID)&b,0,0);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONDOWN:
        LButtonEvent b;
        b.x=(int)(short)LOWORD(lParam);
        b.y=(int)(short)HIWORD(lParam);
        b.k=wParam;
        L->onLButtonDown(b);
        break;

    ....
    }

    return 0;
}
点赞
用户3197530
用户3197530

我不会使用不同的函数来区分两种(或更多种)类型。使用元表!这样,您不需要知道确切的类型,只需使用唯一可用的函数,它将执行正确的操作。

这里可以看到如何完成此操作,但请记住,有更好的方法来创建和打开库。

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include <stdio.h>

int create_person(lua_State* L)
{
    int age = lua_tointeger(L, -2);
    const char* name = lua_tostring(L, -1);

    lua_newtable(L);
    lua_pushinteger(L, age);
    lua_pushstring(L, name);
    lua_setfield(L, -3, "name");
    lua_setfield(L, -2, "age");

    luaL_setmetatable(L, "personmeta");

    return 1;
}

int print_person(lua_State* L)
{
    lua_getfield(L, -1, "name");
    const char* name = lua_tostring(L, -1);
    lua_getfield(L, -2, "age");
    int age = lua_tointeger(L, -1);

    printf("Name: %s\nAge : %d\n", name, age);
    return 0;
}

int create_paper(lua_State* L)
{
    int width = lua_tointeger(L, -3);
    int height = lua_tointeger(L, -2);
    const char* color = lua_tostring(L, -1);
    lua_newtable(L);

    lua_newtable(L);
    lua_pushinteger(L, width);
    lua_pushinteger(L, height);
    lua_setfield(L, -3, "height");
    lua_setfield(L, -2, "width");

    lua_pushstring(L, color);
    lua_setfield(L, -3, "color");
    lua_setfield(L, -2, "dimensions");

    luaL_setmetatable(L, "papermeta");

    return 1;
}

int print_paper(lua_State* L)
{
    lua_getfield(L, -1, "color");
    const char* color = lua_tostring(L, -1);
    lua_getfield(L, -2, "dimensions");
    lua_getfield(L, -1, "width");
    lua_getfield(L, -2, "height");
    int height = lua_tointeger(L, -1);
    int width = lua_tointeger(L, -2);

    printf("Paper: { %d, %d, %s }\n", width, height, color);
    return 0;
}

int luaopen_llib(lua_State* L)
{
    // initialization

    // create metatable for persons
    luaL_newmetatable(L, "personmeta");
    luaL_newmetatable(L, "personmeta");
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, print_person);
    lua_setfield(L, -2, "print");
    lua_pop(L, 1);

    // create metatable for paper
    luaL_newmetatable(L, "papermeta");
    luaL_newmetatable(L, "papermeta");
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, print_paper);
    lua_setfield(L, -2, "print");
    lua_pop(L, 1);

    // create library table and store the creation functions
    lua_newtable(L);
    lua_pushcfunction(L, create_person);
    lua_setfield(L, -2, "create_person");
    lua_pushcfunction(L, create_paper);
    lua_setfield(L, -2, "create_paper");
    return 1;
}

Lua测试代码:

local llib = require "llib"

local p = llib.create_person(33, "David")
p:print() -- Name: David
          -- Age : 33

local paper = llib.create_paper(210, 297, "white")
paper:print() -- Paper: { 210, 297, "white" }

当然,您需要相应地命名此库。

如果需要使用userdata,则可以使用相同的方式。Userdata可以有元表。

2016-11-02 07:24:37