SIDEBAR
»
S
I
D
E
B
A
R
«
Binding C++ to Lua, Part 2; Binding Our First Class
May 23rd, 2010 by dholm

This part will be rather short and summarize part one by providing a very simple sample using our Luna implementation.
Let’s begin by creating a very simple class which we call Test along with a Lua binding LuaTest which will be the intermediate between C++ and Lua.

#include <iostream>

#include "Luna.hpp"

class Test {
public:
    Test(int x) : m_x(x) { }
    int getValue() const { return m_x; }
private:
    int m_x;
};

The test class is a simple getter that provides a method, getValue, which will return the value set in the constructor.
In order to make this class available from Lua we need to write a binder class which translates to and from C++ and Lua code, called LuaTest for the sake of simplicity.

class LuaTest {
public:
    LUNA_TYPES(LuaTest);

LUNA_TYPES(LuaTest); is a simple macro which injects the class with a couple of placeholder variables used by Luna.

LuaTest(lua_State* l) : m_test(luaL_checknumber(l, 1)) { }
    LuaTest(int x) : m_test(x) { }

We need to set up two constructors, one for Lua and one for C++ which emulates the same functionality as the C++ version. The C++ constructor for LuaTest is pretty straightforward but the Lua version is a bit more tricky.
All Lua calls only take a pointer to the actual Lua state since all values are pushed and pulled onto the stack. in this case we use luaL_checknumber(l, 1). This function call will return the first element on the top of the stack assuming it’s a number otherwise it will trigger an error.

int getValue(lua_State* l) {
    lua_pushnumber(l, static_cast<double>(m_test.getValue()));
    return 1;
}

This time we use lua_pushnumber(l, static_cast<double>(m_test.getValue())); to get the value from the stored Test object instance. Not that all numbers in Lua are in double so we need to cast them when expecting something else.

private:
    Test m_test;
};

LUNA_CLASS(LuaTest, Test, Test) = {
    LUNA_METHOD(LuaTest, getValue),
    {0}
};

The LUNA_CLASS macro is used to register the class along with exposing methods calls, if any, the list has to be terminated with a {0}. The first argument to LUNA_CLASS is the name of the binding class, the second the actual C++ class name and the last the identifier to be used from Lua scripts. This way you can for instance bind a boost class to Lua like: LUNA_CLASS(LuaDate, boost::gregorian::date, Date)

int main(int argc, char** argv)
{
    lua_State* l = lua_open();
    luaL_openlibs(l);
    Luna<LuaTest>::commit(l);
    luaL_dofile(l, argv[1]);
    lua_close(l);
    return 0;
}

We create a very simple main function, compile it and pass it the following Lua code:

print("begin")
test = Test(1)
print("Test=" .. test:getValue())
print("end")

The resulting output is left as an exercise to the reader.

In the next installment I will move on to some more advanced features such as instantiating specific C++ classes from within Lua scripts.


One Response  
  • Nicolas writes:
    June 18th, 201001:32at

    Very nice article. Awaiting the third part.


Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

SIDEBAR
»
S
I
D
E
B
A
R
«
»  Substance:WordPress   »  Style:Ahren Ahimsa
Fork me on GitHub