Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm writing a game engine that uses C++ and Lua (and Luabind).

Currently, I'm writing all the bindings inside the constructor of the class being binded. I really don't like this because it's cluttering up my code.

Where should I put the Lua glue code so that it is out of the way and not cluttering up my codebase?

share|improve this question
add comment

closed as off-topic by Nicol Bolas, Anko, Sean Middleditch, Byte56 Jul 16 '13 at 17:06

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions that aren't specific to game development are off-topic here, but can be asked on Stack Overflow. A good rule of thumb is to ask yourself "would a professional game developer give me a better/different/more specific answer to this question than other programmers?"" – Nicol Bolas, Anko, Sean Middleditch, Byte56
If this question can be reworded to fit the rules in the help center, please edit the question.

2 Answers

up vote 6 down vote accepted

The method I have used with good results is to give each class that needs Lua bindings a static class method with the following signature:

static luabind::scope luaBindings();

The definition of this method looks like this:

luabind::scope
MyClass::luaBindings() {
    using namespace luabind;
    return class_<MyClass>("MyClass")
        .def(constructor<>())
        .def("someMethod", &MyClass::someMethod)
    ;
}

Then, in some other place, I initialize the Lua state like this:

void
initializeLua(
    lua_State* L
) {
    luabind::open(L);
    luabind::module(L) [
        MyClass::luaBindings(),
        MyOtherClass::luaBindings()
    ];
}

This way, all Lua bindings are contained in the static class methods. The Lua state is initialized in a very controlled way, without headaches about the order that classes are exported in.

The only downside I have encountered so far is that the initializeLua function needs to know all the classes being exported. Depending on the number of classes, this will result in a rather large list of included files and potentially long compilation times. If that's an issue for you, you can build the luabind::scope hierarchically like this:

luabind::scope
moduleABindings() {
    return (
        MyClass::luaBindings(),
        MyOtherClass::luaBindings()
    );
}

luabind::scope
moduleBBindings() {
    return (
         Foo::luaBindings(),
         Bar::luaBindings()
    );
}

void
initializeLua(
    lua_State* L
) {
    luabind::open(L);
    luabind::module(L) [
        moduleABindings(),
        moduleBBindings()
    ];
}

By separating those functions into separate compilation units, a small change in one of the exported classes' headers will not require recompiling the whole initializer, just the module that has changed.

share|improve this answer
    
This is neat. Could you briefly explain what this is/does? class_<MyClass>("MyClass") .def(constructor<>()) .def("someMethod", &MyClass::someMethod) I'm having trouble understanding it. –  Steven Lu Jul 15 '13 at 23:43
1  
@StevenLu That line exports the MyClass class with an empty constructor to the Lua scripting engine followed by defining a method someMethod on Lua's MyClass definition and that method call invokes the C++ method MyClass::someMethod. –  crancran Jul 16 '13 at 4:32
    
Is constructor<> a type defined by Lua's C++ API? Last I played with Lua it had no C++ stuff. edit: Ah, I recognize it now. It's Luabind! –  Steven Lu Jul 16 '13 at 5:51
add comment

0) Move your constructor to a separate file, there's no rule that says your entire class has to be all in one physical .cpp file.

1) Put your binding code in a separate function in a different file, have the constructor call it? This would be the preferred method.

2) write your binding code in a separate file, inline, and #include it directly into your constructor. This is an oldschool way to get around, not so great these days.

fn::fn()
{
#include "clutter.txt"
}

At least that way it's only cluttering up your project and not the code you see on a daily basis.

share|improve this answer
    
There's no reason it has to be in the constructor for the object. I just put it there because it was the simplest place to put it. I'd rather have it out of the class entirely. –  DormoTheNord Jul 15 '13 at 3:34
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.