Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Library design - C++ bindings to Lua

This thread is locked; no one can reply to it. rss feed Print
Library design - C++ bindings to Lua
Goodbytes
Member #448
June 2000
avatar

As an offshoot of a game project I am working on now, I am looking to replace luabind with something of my own. Luabind is a library which allows you to easily bind C++ classes & functions to Lua scripts. Luabind is nice, but it is also very complicated, hard to mess around with, and very slow to compile. My "replacement" is called Lua-Charon, and it uses the preprocessor and some templates to achieve mostly the same stuff as luabind. It might not end up quite as fully-featured, but it won't require boost, which luabind does, and I hope that it will be easier to extend. Also, so far, it compiles within a project in a fraction of the time that luabind takes.

It looks like the first release will be about 500-600 lines of code, so I figure either I must be missing something or luabind is just way too complicated. If any of you use luabind, could you tell me what features of that library you use most often, and would want in this library, besides binding C++ classes, functions, constants, (etc) to Lua, and the class syntax it adds to Lua? I'm not sure if my first release will support deriving Lua classes from C++ classes. If I know what people use, I can prioritize things...

It works like this: you make a specially formatted header file called lua_modules.h, and add lua_charon.cpp and lua_charon.h to your project. lua_charon.cpp includes your lua_modules.h file several times, each time with different #define macros, in order to generate wrapper functions and then register them with Lua. In your code, you call open_module(L, "modulename") to register a given module with Lua, and close_module(L, "modulename") to close it (does anyone think that the ability to close a module would be useful?) lua_module.h would look something like this:

begin_module("MyModule")
    begin_namespace("Allegro")
        constant(GFX_AUTODETECT, "GFX_AUTO")
        function(ret0 /* discard return value */, set_gfx_mode, "SetGfxMode", arg5(int, int, int, int, int))
        function(ret1(int), makecol, "MakeCol", arg3(int, int, int))
        begin_class(MyBitmap, "Bitmap")
            constructor(MyBitmap, arg2(int, int))
            method(ret0, MyBitmap, Clear, "Clear", arg1(int))
            operator_equals(...) // etc.
        end
    end
end

And with this, in Lua you will be able to do:

Allegro.SetGfxMode(Allegro.GFX_AUTO, 640, 480, 0, 0)
local bitmap = Allegro.Bitmap(640, 480)
bitmap:Clear(Allegro.MakeCol(255, 255, 255))

Any thoughts on the way things work? If you have suggestions or comments, I'd appreciate them!


--
~Goodbytes

Billybob
Member #3,136
January 2003

So far I've only used it to bind my data and utility classes to Lua so my scripts can perform some customizable work. So, just being able to define classes, members, methods, enums, and the like is good enough for me.

I know others have used the feature where you derive a lua class from a C++ class. It's used in game engines, so that you can define Entity in C++ and the engine can process all the entities, and then the scripts can derive Entity into all the different variations it needs.

Do you plan to get rid of the need to define return type and arguments in future versions? And I'm not sure how I feel about a header. Thinking about it, I don't see any problems with it personally, but others might want to split their declarations up throughout their code, in which case the header way of declaring will cause them pain :P. Doing declarations in code isn't too difficult; just requires some template and Singleton magic.

Anyway, good luck! And thanks for working on a project like this. luabind is getting very outdated :-/

nonnus29
Member #2,606
August 2002
avatar

Looks good to me, although I've not used lua or lua bind so I don't know how usable it would be 'in the real world'.

Do you remember Marcello's javascript/spidermonkey c++ binding thing? What's it called....? Anyway, lua and spidermonkey had similar ways of interfacing with external languages. I think he parsed a c++ header files to get information.

tobing
Member #5,213
November 2004
avatar

I'm using LUA as well, and I really it, but from all the currently available bindings I have seen (there's a long list on the lua addons page), there was no one that I liked. Either they have parsing, which complicates the make process. Or they use #define and includes like you do, which is sometimes hard to understand, and limits the use of source code oriented tools like Visual Assist and Workspace Whiz. Or they use templates, but base everything on boost, which is a dependency I have successfully avoided so far. So I use the LUA API directly, and put things into classes and template classes as I see fit. Nothing for general use however, so I appreciate your work very much!

What I use most is calling functions back and forth between the script and the game, exchanging data which usually is organized in tables. Most of the parameter analysis I do by hand now, which is not very elegant, so I would be happy to replace that by something else - if that makes life easier of course.

Goodbytes
Member #448
June 2000
avatar

Billybob: The need for specifying return values and arguments is a) to avoid too much template code (which is what I presume slows down luabind so much... actually, it's probably boost) and b) to allow for more customization, like casting the type or specifying default values for arguments. The biggest problem with using #define macros is that they don't allow overloading. Otherwise I might put some "default" behaviour in which would make things prettier. It's still at an early stage of development, so anything could happen. I'll look into allowing the specification throughout code, and more use of templates (perhaps it wouldn't be too slow). It would be nice.

nonnus: I vaguely remember it. But I don't want to make Lua-Charon a parsing tool, because, as tobing said, it complicates the make process. I prefer something native to C++.

tobing: I will adopt your dislikes about currently available bindings as my design goals. Maybe I can't overcome all of them, but at least my library has the coolest name.

Much like Charon of Greek mythology, Lua-Charon ferries the dead husk of your C++ code across the swamps of Acheron to the eternal paradise of Lua. Sorry, Orpheus: he can't bring code back. ;)

Thanks for the feedback so far, everyone. If I come up with more code today / an updated design, I'll post it here.


--
~Goodbytes

Peter Hull
Member #1,136
March 2001

Does Swig work with Lua? It doesn't say it does on the homepage, but it does have a link to lua.org.

Pete

Goodbytes
Member #448
June 2000
avatar

http://www.swig.org/compat.html#SupportedLanguages said:

Support for Lua, CLISP and Common Lisp with UFFI was added in SWIG-1.3.26.

So it does, but it's a tool too, not native code.

[EDIT]
I have overcome the requirement of specifying return types / argument types, and changed the order of arguments so the Lua name is always first. My hypothetical example from above now looks like this (begin_class and related macros are not yet implemented):

begin_module("MyModule")
    begin_namespace("Allegro")
        constant("GFX_AUTO", GFX_AUTODETECT)
        function("SetGfxMode", set_gfx_mode)
        function("MakeCol", makecol)
        begin_class("Bitmap", MyBitmap)
            constructor(MyBitmap::MyBitmap)
            method("Clear", MyBitmap::Clear)
            operator_equals(...) // etc.
        end
    end
end

I plan to add a series of _ex macros for more customization (discarding or modifying return values, default parameters, etc.). Currently, up to 12 function arguments are supported. I may add support for variadic arguments.

For now, I'll stick with the mechanism of a single registry file for registering modules. Lua-Charon may eventually become a template-only solution. If that happens, the single registry file requirement will disappear.

Does anyone have comments on the syntax of the registry file? Does it seem unwieldy or unaesthetic, or nonsensical? (e.g., there are no constants in Lua, so maybe "constant" should be called "value" or "variable" or "global.")


--
~Goodbytes

Billybob
Member #3,136
January 2003

YAY! Looks good :)

Just another note (heh, sorry :P ): Don't forget support for static class members and methods. And watch out for overloaded methods and functions.

Goodbytes
Member #448
June 2000
avatar

Billybob: I won't! I can't go a day without static class members and methods. (well...)
The overloaded methods and functions would be dealt with the same way as in luabind: you just tell lua-Charon which overload you're referring to with a function pointer cast. I suppose implementing it on the Lua side might be an extra gotcha. Though it'd be nice if I could figure out a way to handle overloading automatically (yeah, right)


--
~Goodbytes

Go to: