|Home - About - Blog - Projects - Contact|
Integrating with LuaPosted by Linkage on 6 February, 2012 at 5:47pm
Under the Christmas tree this year came (amongst everything else) a copy of Programming in Lua- just what I had asked for (believe it or not). I got to reading through it over the last month or so and- setting aside the fact that Lua 5.3 came out just recently, rendering the book a little outdated- thought I’d have a go at utilising the Lua C API to get some integration going in a simple project.
I took a version of StealthDemo that I had previously stripped down to its most basic parts- basically just a base ‘OBJECT’ class along with various foundational/graphics code. My goal was to allow an external Lua script to create, access, and control in-game objects through script-defined types in a style akin to this:
Starting up with the Lua C API takes a little getting used to mainly because of the stack system used to exchange values between Lua and C. Anyone familiar with stack operations shouldn’t have much trouble getting their head around manipulating the Lua stack (it’s just an ordinary stack after all) but changing your mentality to get various values and arguments off the stack takes some getting used to (plus some care); I’ve already once completely forgotten about having to push arguments to functions on the stack before running a lua_pcall.
The first problem to face in my desired integration is how to store an in-game object- that is, an instance of the OBJECT class- in such a way that can be accessed both by the game engine (if you could call this bare-bones implementation an ‘engine’) and Lua itself. My method of storing any in-game objects normally comprises of simply storing a vector<> of all objects, which in this case I changed instead to a vector of smart-pointers (provided by the Boost C++ libraries) allowing me to use dynamic allocation more often should I so choose (especially since this provides the opportunity to utilise polymorphism more fully in my code later on). On the other hand, Lua’s primary facility for integrating C/C++ structures with Lua is userdata- basically memory allocated and managed by Lua holding C data that you can provide an interface to with various C functions.
In deciding how to use/mix these two options, one of the most important factors is ownership. The biggest conflict arises in making sure only one system ‘thinks’ it owns the data- Lua garbage-collects userdata along with its own data, so you don’t want that messing with data kept in your game-state, or similarly you might want to let Lua do its thing and instead make sure that your game-state knows not to free the memory that isn’t its own. The method I used was to let the memory of new objects be controlled by my vector of pointers- creating objects with ‘new’ as necessary- and instead pass off to Lua a pointer to the data, so ownership is maintained by the game and- more importantly- Lua can destroy its own pointer data without interfering with anything else. To accomplish this I first looked at light userdata, which is just that- a void pointer to application-owned memory, but the problem there is that light userdata does not allow for the usage of metatables- which are crucial to allowing object-oriented access for the end-user- so instead I stuck with normal userdata, and simply requested the size of a pointer.
Sign in or sign up to post a comment!
Website Design and Coding by Chris Lewis|
Thanks to Ming for much help with Layout Design