Tutorial: Using luabind to integrate Lua with C/C++ (pt.2)

In the last week article we discussed some basic things about the luabind library and how to integrate it to your Xcode project. For this week iDevBlogADay post, I will show you how to expose some more complex C++ code to the Lua runtime.

I also want to add that I’m on vacations in Cordoba Argentina, and that this post was published ( or not :D ), using the wordpress scheduling function ( which I really hope to work without any issue! ).

Let’s start right away, let’s say we have the following Class definition:

//Image.h
 
#include "luabind.hpp"
 
class Texture2D;
 
class Image
{
    Texture2D   *texture;
 
public:
    Image();
    ~Image();
    void initWithTexture(const std::string &textureName);
    void initWithTexture(Texture2D *aTexture);
};

As you can notice the initWithTexture method is overloaded, luabind needs that we specify the exact method signature that we want to expose to Lua , but if your C++ is not rusty it shouldn’t be hard.

Let’s say that we wanted to expose the initWithTexture method that takes a string from the previous code fragment, and also the Image class itself.

Here’s the correct way of doing it:

luabind::module(LuaState) 
[
 luabind::class_<Image>("Image")
 .def(luabind::constructor<>())
 .def("initWithTexture", (void(Image::*)(const std::string &))&Image::initWithTexture)
 ];

Notice how in line 5, I had to specify the return value of initWithTexture ( void ), the args, (const std::string &) and then the pointer to the method (&Image::initWithTexture).

Another very useful property of luabind, is that we can set a class property in a special way using custom getters and setters in the C++, let’s say we have the same class but we add a float scale property.

//Image.h
 
#include "luabind.hpp"
 
class Texture2D;
 
class Image
{
    Texture2D   *texture;
    float scale; // we added this property
public:
    void initWithTexture(const std::string &textureName);
    void initWithTexture(Texture2D *aTexture);
    float getScale(){ return scale; }
    float setScale(float in_scale) { scale = in_scale }
};

With luabind we can expose those setters in a special way to define a Lua property:

luabind::module(LuaState) 
[
 luabind::class_<Image>("Image")
 .def(luabind::constructor<>())
 .def("initWithTexture", (void(Image::*)(const std::string &))&Image::initWithTexture)
 .property("scale", &Image::getScale, &Image::setScale) // added this line
 ];

Having done all this, from Lua we could do:

-- This is a Lua Script
newImage = Image()
newImage:initWithTexture("zombie_face")
newImage.scale = 0.5

I like to put the luabind::module code in a static function inside the Image Class, I execute that code when my game starts using basic templates:

#include "luabind.hpp"
 
class Texture2D;
 
class Image 
{
    Texture2D *texture;
    float scale;
 
public:
    void initWithTexture(const std::string &textureName);
    void initWithTexture(Texture2D *aTexture);
    float getScale();
    void setScale(float in_scale);
 
    static void registrate(void)
    {
        luabind::module(LuaState) 
        [
         luabind::class_<Image>("Image")
         .def(luabind::constructor<>())
         .def("initWithTextureFile", (void(Image::*)(const std::string &))&Image::initWithTextureFile)
         .property("scale", &Image::getScale, &Image::setScale)
         ]; 
    }   
};

I then use this function to call registrate() on all the Classes that implement it:

//The registrate function takes a Class name and calls its registrate method
template <typename T>
void registrate() {
    T::registrate();
}
 
//I can use it like this to bind my Image class to Lua.
registrate<Image>();

I know most of you guys do a lot of Objective-C, but I think this is starting to change a bit, at least when it comes to games if you want to go multi-platform or are thinking on easing up your transition to another platform, C++ can come in handy when you finally happen to pull the trigger.

I hope you enjoyed this week’s article and see you next Friday! :D



Comments

Add Yours

  • Author Avatar

    YOU


Comment Arrow



About Author

Nicolas Goles

Gando Games Founder and Lead Engineer, Nicolas is also a software Engineering Student in Santiago, Chile. Mostly developing Games and Utilities for iPhone/iPad/iPod Touch with C/C++/Obj-C and some lua. He has also worked in Mobile Peer-to-Peer (P2P) application and prototype development.