When initializing your module you can store the lua_State* locally within the module.
The lua_State* object is the core for all accesses between Lua and C/ObjC/C++. While it can’t be guaranteed to persist as long as you reference it, since Corona can shut it down when it’s done, it’s very difficult to get into a situation where Corona has shut down it’s Lua environment and you are still running stuff with it.
Once you have that Lua_State available, you have a few solutions: Callback, Global Event, Local Event(Like Runtime:DispatchEvent, but to a specific object in the _G table). I prefer the Callback registration method. However, since the C-side Lua library doesn’t have a structure for Lua Function (Only Lua Function declared in C), Storing specific callbacks can take a little more than expected. Here is a quick example of registering a Lua-side callback for use with a C-side function.
Obj C
static lua\_State\* state; //This is all static because I am very lazy
static int callbackIndex = 0;
static int errorIndex = 0;
//Call this to register functions for callbacks
int
FakeModule::registerCallback(lua\_State\* L)
{
if (errorIndex \> 0)
{
luaL\_unref(L, LUA\_REGISTRYINDEX, errorIndex);
}
errorIndex = luaL\_ref(L, LUA\_REGISTRYINDEX);
if (callbackIndex \> 0)
{
luaL\_unref(L, LUA\_REGISTRYINDEX, callbackIndex);
}
callbackIndex = luaL\_ref(L, LUA\_REGISTRYINDEX);
return 0;
}
//This is where you recieve an ObjC callback and forward it into LUA (via your registered Callback)
void
FakeModule::callbackFunc(NSString name, int index)
{
if(callbackIndex \> 0)
{
lua\_rawgeti(state, LUA\_REGISTRYINDEX, errorIndex);
lua\_rawgeti(state, LUA\_REGISTRYINDEX, callbackIndex);
lua\_pushstring(state, [name UTF8String]);
lua\_pushinteger(state, index);
lua\_pcall(state, 2, 0, -4); --Calls callback function with error function as error handler
}
}
const char \*
FakeModule::Name()
{
static const char sName[] = "MyModule";
return sName;
}
int
FakeModule::Open( lua\_State \*L )
{
state = L;
const luaL\_Reg kVTable[] =
{
{ "registerCallback", registerCallback },
{ NULL, NULL }
};
// Ensure upvalue is available to library
void \*context = lua\_touserdata( L, lua\_upvalueindex( 1 ) );
lua\_pushlightuserdata( L, context );
luaL\_openlib( L, Name(), kVTable, 1 );
return 1;
}
Lua
local file = {}
local function onError(errorStr)
print("ERROR IN PLUGIN", errorStr)
end
local function onCallback(name, index)
print("Called Back", name, index)
end
--This is a neat trick for wrapping plugins so that they silently fail in Simulator.
--It allows you to attempt to load the module, but if it's not there, simply don't forward calls
local plugin = nil
local pluginFunc = package.preload["MyModule"]
if pluginFunc then
plugin = pluginFunc()
plugin.registerCallback(onCallback, onError) --Registers your Callbacks with the C-side
end
--Add functions here as
--function file.pluginFunction(parameters)
-- if plugin then plugin.pluginFunction(parameters) end
--end
--To allow for easy disabling of plugin detection for Simulator builds (and if you port to Android you just need to load the Android plugin module and POW it works
return file
The Lua_Ref and RegisteryIndex may be new, but essentially Lua_Ref/Lua_Unref adds the variable at the top of the stack to a specific table index. It takes the lowest available integer index, and returns you that index. RegistryIndex is a Lua table that is only accessible from the C-side library. It allows you to store Lua values in a Garbage-collection safe way on C-side, that is not just sitting around in _G.
As well, if you store the lua_state you can setup the proper stack variables to call RuntimeDispatchEvent.
This is written pretty hastily, let me know if you have more questions.
ADDED: Also if you need to process a callback response, you should be able to pull it directly from the lua_State after pcall (using Lua’s to_[Type] functions). [import]uid: 134101 topic_id: 32964 reply_id: 130938[/import]