Do It Yourself Cpp Binding

lua-users home
wiki

When programming my game engine, and specifically integrating Lua from the get-go, I considered quite a few binding generators, such as SWIG, tolua, SimplerCppBinding, etc. None of them quite served my needs:

Here's a few tricks I've found, mostly in code form, which work together:

creating metatables

lauxlib has really, really useful functions for manipulating userdata metatables. Those are adequately covered in the [Lua Auxiliary Library] in the reference manual. I suggest giving each metatable a name identical to the classname; this will enable fun and evil preprocessor tricks like those that follow here. To those unfamiliar with the operator: the # operator in #define statements will cause the following argument to be placed in quotes when the macro is expanded.

checking argument types

A useful macro to simplify checking whether the object at a given stack position is of a given userdata type (registered with luaL_newmetatable):

#define lua_userdata_cast(L, pos, T) static_cast<T*>(luaL_checkudata((L), (pos), #T))

I use stuff like this a lot in my metamethods:

if(const MyClass* myclass = lua_userdata_cast(L, 1, MyClass))
{
    MyClass->SomeMethod();
    return 0;
}

placement new to avoid boxed pointers

Dig it:

void* operator new(size_t size, lua_State* L, const char* metatableName)
{
    void* ptr = lua_newuserdata(L, size);
    luaL_getmetatable(L, metatableName);
    // assert(lua_istable(L, -1)) if you're paranoid
    lua_setmetatable(L, -2);
    return ptr;
}

#define lua_pushobject(L, T) new(L, #T) T

Now, instead of doing boxpointer weirdness, to push an object of a type whose metatable was created with luaL_newmetatable onto the stack, do like so:

lua_pushobject(L, MyClass)(arg1, arg2, arg3);

...thus allowing you to construct a new MyClass directly into the memory region it'll be using!

templated __gc method

watch this:

template<typename T>
int GCMethod(lua_State* L)
{
    static_cast<T*>(lua_touserdata(L, 1))->~T();
    return 0;
}

This templated method makes a perfect __gc method. Like so:

lua_pushstring(L, "__gc");
lua_pushcfunction(L, GCMethod<MyClass>);
lua_settable(L, 1);

See Also


RecentChanges · preferences
edit · history
Last edited February 23, 2014 4:22 pm GMT (diff)