Just in case any else might find it useful, I made a bit more progress on my project to add multiple timers to lua. Here are a few comments and code snippets
I had a look at the lalarm example Luis posted for me, that was very helpful but it had a similar issue that I raised in my first post regarding globals.
That example code also needed the lua state variable L inside the timer handler. It did a similar trick of copying L to a global LL variable and using LL in the handler.
I have now removed the global from my code, I was lucky to discover that the OS I am using has a timer create C function that allows a userData parameter to be specified when the timer is created, this parameter is then passed into the timer handler when it fires. So I now pass in L for userData which means I no longer need the global variable.
Ignoring the debate about whether to use hand coded API bindings or which automatic binder is best. I like the convenience of Swig, so my preferred approach is use Swig for most of my simple functions, and hand code where Swig cant do what I need.
Initially though I wasnt sure how I could add the hand bound functions to the Swig generated namespace. It turned out this wasnt difficult to do in the end.
Not sure if this is a way to post code here without the HTML formatting being screwed up ? Sorry if this isnt easy to read
// # Snippet from my Task initialisation code
luaopen_myLib(L); // Declare the Swig wrapped module. Swig version must be before the luaopen_myLib() call
luaopen_myLib2(L); // Declare the manual bound functions that append to the swig myLib namespace
LUALIB_API int luaopen_myLib2(lua_State *L)
initLuaTimers(); // Inits the OS timer component and sets up a C array to keep track of 20 timers
// Stk: ...
lua_getglobal(L, "myLib"); // get the myLib table onto the top of stack
// Stk: ... Tbl
// Stk: ... Tbl "createTimer"
// Stk: ... Tbl "createTimer" C-Function
lua_settable(L, -3); // adds "createTimer" to myLib namespace
// Stk: ... Tbl
-- so from Lua this would be
local timerID1 = myLib.createTimer(luaTimerCallback1, 500) -- make a 0.5 Sec timer
This work did raise one other question in my mind about namespaces, I might post a follow up question on that later
Date: Mon, 21 Feb 2011 13:51:11 +0000
Subject: Timers, Callbacks & Swig
Newbie here, my first post to this list, hope I am doing it correctly ?
I am trying to add to my embedded App. the ability for Lua to have up to say 20 timers the user can create with asscociated Lua callback functions. The timers will be implemented in C with my underlying OS (not Windows). So from Lua it would read something like ..
print ("Lua callback function One.\n")
print ("Lua callback function Two.\n")
local timerID1 = myLib.createTimer("luaTimerCallback1", 3000) -- 3 Seconds
local timerID2 = myLib.createTimer("luaTimerCallback2", 5000) -- 5 Seconds
I am implementing the createTimer binding to C with SWIG, so my C function is
int createTimer(char *funcName, unsigned int periodInMs)
Having to make the Callback function name a string, looks a bit wrong to me, I would have preferred to just pass it as a Lua function, but I couldnt figure out a way to do that with SWIG. Is it even possible to pass a Lua function back into C without having to pass it as a string ? If so any clues how to do it please ?
In my C function I then do some API calls to store the LUA function name in the LUA registry, I then create the timer in C, and let it run. When the timer fires, I look up the specific Lua function from the registry and then call that with a pcall function. This works OK.
The API code I have put inside my C createTimer() function of course needs to get the Lua state variable L, for example a line such as lua_getglobal(L, funcName); etc
But the snag I hit is how do I get the Lua state variable L ? It was passed into my Swig binding when I registered it with Lua with the line
luaopen_myLib(L); // declare the wrapped module
but I cant see how I can get at that variable from inside my createTimer() C function ? Anyone any ideas ?
For the moment I have kludged it by saving it in a global. This works but dont want to use it as the final solution as it wont work if I need to have multiple Lua states running in different OS threads.
Maybe I just need to implement this timer code without using SWIG ? But even if I could work out how to do that, I am not sure how I would then add this manual binding to my myLib Swig bindings ? Any ideas how to add manual bindings to the mylib Swig auto bindings ?
Any thoughts or code examples would be appeciated, thanks