【发布时间】:2010-10-11 10:15:46
【问题描述】:
我有一个用 swig 包装的类,并用 lua 注册。我可以在 lua 脚本中创建这个类的一个实例,并且一切正常。
但是假设我有一个在我的 c++ 代码中创建的类的实例,并调用了 new X,并且我有 la lua_state L,其中有一个我想调用的函数,它接受一个参数,一个 X 的实例...我如何调用该函数。这是(一些)有问题的代码(我省略了错误处理的东西):
main.cpp
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);
}
mainmenu.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 对评论的回应
GuiInst 的构造函数在 swig 运行时被 #defined 为私有,以防止 lua 构造它的实例,所以这对我不起作用。我试图阻止的是以下(在 lua 中):
r=engine.GuiRegionVertical()
r:Add(engine.GuiButton())
它会调用“g=new GuiButton”,然后将它注册到 GuiRegionVertical(由于各种原因需要存储一个指针),然后调用“delete g”,GuiRegionVertical 会留下一个指向 g 的悬空指针。
我怀疑真正需要发生的是 GuiRegionVertical::Add(GuiButton*) 应该增加 GuiButton* 的引用计数,然后 GuiRegionVertical 的析构函数应该减少其所有内容的引用计数,尽管我不确定swig 应该如何做到这一点。
这将消除对私有构造函数、Gui 对象工厂和讨厌的外部对象的需求。
我这样做错了吗?
谢谢。
【问题讨论】:
-
@NicolBolas:这个问题怎么可能是重复的?它比那个大三岁:)。谢谢你的链接。