Lua Binding Woes

January 20th, 2009, Code Stuff, Lua

Lua LogoAs you know, we’ve been using Lua to make prototypes and add mod support to Harvest. However, I’ve always thought that the C++ binding we’ve used hasn’t really worked the way I’d like it to. Basically we’ve used simple C functions to create our own Lua library for callbacks, and some Lunar objects in Harvest. Lunar allows you to do stuff such as this:

local stuff = lib.getStuff()
stuff:foobar() — call C++ member method

However, it doesn’t allow you to do this:

local stuff = lib.getStuff()
stuff.onEvent = function(self) print(”Recieved event!”) end

The problem is that with Lunar all objects of the “stuff” class share the same meta table. It’s possible to modify the meta table in Lua by calling getmetatable(), but then you will be modifying the meta table of all instances of “stuff…”

In other words I needed a new solution. A friend over at #gamedev (at QuakeNet), Joris “Interface” de Gruyter, gave me a link to a Lua in C++ article at CodeProject. That was great, it had all kinds of useful stuff, but it required the script to be run for each object because it used a “this pointer” method, such as:

this:foobar() — call C++ member function
this.onEvent = function(self) end — create callback function

I can imagine this kind of system is great for certain kinds of projects, since it cleans up the Lua code and places different objects into different Lua files. However, this was still not what I wanted! So I scratched my head a while and looked around in the code of the two options… and then I realized they were combinable!

So the solution I used was to create a new Lunar-like class (called “Lunamatic,” after a famous Akarra/Harvest player), since it had that nice member-function pointer stuff, but instead of placing the meta table information in the global scope I recreated the table for every instance of the class. As you can imagine, this is less efficient than using a shared table, so it’s not useful in every situation, but sometimes. This way I could achieve what I was really looking for, namely:

local button1 = gui.createComponent(”button”)
local button2 = gui.createComponent(”button”)
button1:moveTo(100, 100)
button1.onClick = function(self) print(”foo”) end
button2.onClick = function(self) print(”bar”) end

Since our WordPress skin isn’t suitable for code dumps, I have put the juicy stuff in our forums. For the interested, pleace follow this link: http://www.oxeyegames.com/forum/viewtopic.php?f=13&t=346

/jeb

PS. The RTS article series will continue “in 2009″ :) DS.

Leave a Reply


Oxeye Game Studio is proudly powered by WordPress
Entries (RSS) , Comments (RSS) and YouTube Widget by Daiko.