Lua C API - 从 C++ 中分配和使用 Lua 类的对象成员

我正在尝试从 C++ 中实例化和使用 Lua 类的对象。Lua 类定义如下:

myclass = {}

function myclass:new(o)
   o=o or {}
   setmetatable(o,self)
   self.__index=self
   return o
end

function myclass:init()
   self.something = 0
end

function myclass:perform()
   self.something = self.something + 0.5
   return performsomething(self.something)
end

为了在 C++ 中实例化对象,我执行以下操作:

lua_getglobal(L,"myclass");
lua_getfield(L, -1, "new");
lua_pcall(L,0,1,0);
lua_newtable(L);
lua_setglobal(L, "objname");

然后进行初始化:

lua_getglobal(L,"myclass");
lua_getfield(L, -1, "init");
lua_getglobal(L,"objname");
lua_pcall(L, 0, 0, 0);

然后执行:

lua_getglobal(L, "myclass");
lua_getfield(L, -1, "perform");
lua_getglobal(L, "objname");
lua_pcall(L, 0, 1, 0);
double res = lua_tonumber(-1);

对于这个例子,我没有包含我在需要时使用的 lua_pop() 方法。

似乎,通过打印,我可以得到以下信息。使用 new 方法成功地实例化了 Lua 对象。在 init 方法中,它也被成功初始化。但是,在调用 perform 方法时,self.something 成员没有变化,它的值保持为 0,这似乎意味着我没有调用对象成员方法。

我相当确定我管理 Lua 堆栈以访问对象成员函数的方式有问题。

有人已经处理过类似情况并可以在这里提供帮助吗? 谢谢 最好的

点赞
用户5675002
用户5675002

很可能你没有在lua_pcall函数中更正nargs参数。

当使用冒号语法(class:func())定义函数时,你必须明确从C/C++端传递self参数。但在你的示例中并没有这样做。

最小程度地更改你的代码,它将如下所示:

Lua端:

function performsomething(x)
    print("type:", type(x))
    print("value:", x)
    return x
end

myclass = {}

function myclass:new(o)
   o=o or {}
   setmetatable(o,self)
   self.__index=self
   return o
end

function myclass:init()
   self.something = 0
end

function myclass:perform()
   self.something = self.something + 0.5
   return performsomething(self.something)
end

C/C++端:

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

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    luaL_dofile(L, "myclass.lua");

    // 实例化
    lua_getglobal(L,"myclass");
    lua_getfield(L, -1, "new");
    lua_getglobal(L, "myclass");
    lua_pushvalue(L, -1);
    lua_pcall(L,2,1,0); // nargs更正为2,表示传递了2个参数,其中一个是self参数
    lua_setglobal(L, "objname");

    // 初始化
    lua_getglobal(L,"myclass");
    lua_getfield(L, -1, "init");
    lua_getglobal(L,"objname");
    lua_pcall(L, 1, 0, 0);

    // 执行
    lua_getglobal(L, "myclass");
    lua_getfield(L, -1, "perform");
    lua_getglobal(L, "objname");
    lua_pcall(L, 1, 1, 0);

    double res = lua_tonumber(L, -1);
    printf("Result: %f\n", res);

    lua_close(L);

    return 0;
}
2019-12-06 18:12:10