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
), 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!




Add Yours
YOU