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)