我有一个用 swig 包装的类,并用 lua 注册。我可以在 lua 脚本中创建此类的实例,并且一切正常。
但是假设我有一个在我的 C++ 代码中创建的类的实例,并调用了 new X,并且我有 la lua_state L,其中有一个我想调用的函数,它接受一个参数,一个 X 的实例......我如何调用该函数。这是(一些)有问题的代码(我省略了错误处理的东西):
主文件
class GuiInst;
extern "C"
{
int luaopen_engine (lua_State *L);
}
int main()
{
GuiInst gui=new GuiInst;
lua_State *L=luaL_newstate();
luaopen_engine(L); //this is swigs module
int error=luaL_loadfile(L,"mainmenu.lua")||
lua_pcall(L, 0, 0, 0);
lua_getglobal(L,"Init");
//Somehow push gui onto lua stack...
lua_pcall(L, 1, 0, 0));
lua_close(L);
}
主菜单.lua
function Init(gui)
vregion=gui:CreateComponent("GuiRegionVertical");
end
目前,我发现可以工作的只是从 swig 生成的 cpp 文件中公开一些功能,然后调用它。由于几个原因,这很糟糕......如果我有多个模块并且我不得不更改 swig 文件中的默认链接规范(使用 -DSWIGRUNTIME=),它将无法工作。
我将以下内容添加到 main.cpp
extern "C"
{
struct swig_module_info;
struct swig_type_info;
int luaopen_engine (lua_State *L);
swig_module_info *SWIG_Lua_GetModule(lua_State* L);
void SWIG_Lua_NewPointerObj(lua_State* L,void* ptr,swig_type_info *type, int own);
swig_type_info *SWIG_TypeQueryModule(swig_module_info *start,swig_module_info *end,const char *name);
}
//and then to push the value...
SWIG_Lua_NewPointerObj(L,gui,SWIG_TypeQueryModule(SWIG_Lua_GetModule(L),SWIG_Lua_GetModule(L),"GuiInst *"),0);
它得到一个指向模块的指针,然后是指向类型的指针,然后调用 swigs 函数来注册它。不得不挖掘一个不应该是人类可读的文件(所以它在文件的顶部说)而且只是混乱,这是一件不合理的事情!(但它确实有效!)
当然,有更好的方法来完成我正在尝试做的事情。
PS 从高级 pov 我想要的是让 lua 不引用由 GuiInst 中的对象工厂创建的 Gui 组件,以防我遇到这个错误。这是我第一次向脚本语言公开功能,除了一些非常简单(和非 swig)的 python 模块,所以我准备接受建议。
感谢您的任何建议!
RBerteig 对评论的回应
当 swig 运行以防止 lua 构造它的实例时,GuiInst 的构造函数是 #defined 私有的,所以这对我不起作用。我试图阻止的是以下(在lua中):
r=engine.GuiRegionVertical()
r:Add(engine.GuiButton())
它将调用“g=new GuiButton”,然后将其注册到 GuiRegionVertical(由于各种原因需要存储一个指针),然后调用“delete g”,并且 GuiRegionVertical 留下了一个指向 g 的悬空指针。
我怀疑真正需要发生的是 GuiRegionVertical::Add(GuiButton*) 应该增加 GuiButton* 的引用计数,然后 GuiRegionVertical 的析构函数应该减少其所有内容的引用计数,尽管我不确定这应该如何痛饮就完事了。
这将消除对私有构造函数、Gui 对象工厂和讨厌的外部对象的需要。
我要解决这个错误吗?
谢谢。