如何在Lua调用C/C++时找到userdata的类型

我使用 Lua 调用 DLL 文件。 我的 C/C++ 代码如下:

#include <iostream>
extern "C"{
    #include "lua.hpp"
    #include "lualib.h"
    #include "lauxlib.h"
}

using namespace std;

typedef struct StructA{
    int a;
} structA;

typedef struct StructB{
    char *b;
} structB;

static int createA(lua_State *L)
{
    int n = lua_gettop(L);
    size_t iBytes = sizeof(struct StructA);
    struct StructA *sa;
    sa = (StructA *)lua_newuserdata(L, iBytes);
    sa->a = 1;
    return 1;
}

static int createB(lua_State *L)
{
    int n = lua_gettop(L);
    size_t iBytes = sizeof(struct StructB);
    struct StructB *sb;
    sb = (StructB *)lua_newuserdata(L, iBytes);
    sb->b = "2";
    return 1;
}

static int print(lua_State *L)
{
    if(lua_type(L,1) == LUA_TUSERDATA)
    {
        void *ud = lua_touserdata(L, 1);
        luaL_checktype(L, 1, LUA_TUSERDATA);
        if(lua_getmetatable(L, 1))
        {
            luaL_getmetatable(L, "occit_structA");
            if(lua_rawequal(L, -1, -2))
            {
                cout<< "struct type is StructA" <<endl;
                struct StructA *sa = (struct StructA *)ud;
                cout<< "a:"<<(sa->a) <<endl;
                return 0;
            }
            luaL_getmetatable(L, "occit_structB");
            if(lua_rawequal(L, -1, -2))
            {
                cout<< "struct type is StructB" <<endl;
                struct StructB *sb = (struct StructB *)ud;
                cout<< "b:"<<(sb->b) <<endl;
                return 0;
            }
        }
    }
    return 0;
}

static luaL_Reg mylibs[] = {
    { "A", createA },
    { "B", createB },
    { "print", print },
    { NULL, NULL }
};

extern "C" __declspec(dllexport)
int luaopen_occi_test(lua_State* L)
{
    luaL_register(L, "occi_test", mylibs);
    luaL_newmetatable(L, "occit_structA");
    luaL_newmetatable(L, "occit_structB");
    return 1;
}

我使用 VS2010 编译了这个 C/C++ 代码。 我的 Lua 代码如下:

local a = occi_test.A()
local b = occi_test.B()
occi_test.print(a)
occi_test.print(b)

如您所见,在 Lua 中,参数 a 和 b 都是 userdata 类型,但在 C/C++ 中,a 的类型是 StructA,b 的类型是 StructB,因此当 Lua 调用 C/C++ 函数并传递 a 或 b 时,如何让 C/C++ 代码找到参数的类型?请在“某些条件”的位置上完成此代码,以便完成此任务。

点赞
用户7509065
用户7509065
  1. luaopen_occi_test 的开始时,执行 luaL_newmetatable(L, "StructA");luaL_newmetatable(L, "StructB");。这将向注册表中添加元表,以便稍后使用。
  2. createAcreateB 结束时,执行 luaL_setmetatable(L, "StructA");luaL_setmetatable(L, "StructB");。这将把步骤1中创建的适当元表附加到新的用户数据对象上。
  3. print 函数中,使用 luaL_testudata(L, 1, "StructA")luaL_testudata(L, 1, "StructB") 进行条件判断。当它是具有指定元表的用户数据时,这将返回一个指向用户数据的指针(转换为布尔值时为真),否则返回一个空指针(转换为布尔值时为假)。另外,您还可以稍加优化代码,先保存结果然后再使用正确的结果,如下所示:
static int print(lua_State *L)
{
    struct StructA *sa;
    struct StructB *sb;
    if((sa = (struct StructA *)luaL_testudata(L, 1, "StructA")) != nullptr)
    {
        cout<< "struct type is StructA" <<endl;
        cout<< "a:"<<(sa->a) <<endl;
    }else if((sb = (struct StructB *)luaL_testudata(L, 1, "StructB")) != nullptr)
    {
        cout<< "struct type is StructB" <<endl;
        cout<< "b:"<<(sb->b) <<endl;
    }
    return 0;
}
2020-11-21 22:45:04