I have a class that is wrapped with swig, and registered with lua. I can create an instance of this class in a lua script, and it all works fine.
But say I have an instance of a class made in my c++ code with a call to new X, and I have la lua_state L with a function in it that I want to call, which accepts one argument, an instance of X... How do I call that function. Here is (some) of the code in question (I've omitted the error handling stuff):
main.cpp
class GuiInst;
extern "C"
{
int luaopen_engine (lua_State *L);
}
int main()
{
GuiInst gui=new GuiInst;
lua_State *L=lua_open();
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
At the moment all I have found that can work is to expose some functionality from the swig generated cpp file, and call that. This is bad for a few reasons... It won't work if I have multiple modulles and I had to change the default linkage specification in the swig file (using -DSWIGRUNTIME=).
I add the following to 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);
That gets a pointer to the module, then a pointer to the type, then calls swigs function to register it. It was an unreasonable thing to have to dig into a file that's not supposed to be human readable (so it says at the top of the file) and is just MESSY! (but it does work!)
Surely theres a better way to accomplish what I'm trying to do.
PS from a high level pov what I want is to have lua not refcount the Gui components which are created by the Object Factory in GuiInst, in case I'm going about this wrong. This is my first time exposing functionality to a scripting language apart from some very simple (and non-swig) python modules, so I'm prepared to take advice.
Thanks for any advice!
Response to comment by RBerteig
GuiInst's contructor is #defined to private when swig runs to prevent lua constructing instances of it, so that won't work for me. What I was trying to prevent was the following (in lua):
r=engine.GuiRegionVertical()
r:Add(engine.GuiButton())
which would call "g=new GuiButton" then register it with the GuiRegionVertical (which needs to store a pointer for various reasons), then call "delete g", and the GuiRegionVertical is left with a dangling pointer to g.
I suspect what really needs to happen is that GuiRegionVertical::Add(GuiButton*) should increment the ref count of the GuiButton*, and then GuiRegionVertical's destructor should decrement the refcounts of all of its contents, though i'm not sure how this should be done with swig.
That would remove the need for the private constructors, the Gui Object Factory and the nasty externs.
Am I going about this Wrong?
Thanks.