自己动手 Cpp 绑定

lua-users home
wiki

在为我的游戏引擎编程,特别是从一开始就集成 Lua 时,我考虑过很多绑定生成器,比如 SWIG、tolua、SimplerCppBinding 等等。但它们都没有完全满足我的需求。

以下是一些我发现的技巧,主要以代码形式呈现,它们共同工作。

创建元表

lauxlib 提供了非常非常有用的函数来操作用户数据元表。这些函数在参考手册的 [Lua 辅助库] 中有充分的介绍。我建议为每个元表命名与类名相同;这将使像下面这样的有趣且邪恶的预处理器技巧成为可能。对于不熟悉该运算符的人来说:# 运算符在 #define 语句中将导致后面的参数在宏展开时被放在引号中。

检查参数类型

一个有用的宏,用于简化检查给定堆栈位置上的对象是否为给定用户数据类型(已使用 luaL_newmetatable 注册)。

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

我在元方法中经常使用类似的东西。

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

放置 new 以避免打包指针

了解一下

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

现在,与其进行打包指针的奇怪操作,不如将一个类型为其元表使用 luaL_newmetatable 创建的对象推送到堆栈上,可以这样做。

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

... 这样你就可以直接在它将使用的内存区域中构造一个新的 MyClass

模板化的 __gc 方法

看看这个

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

这个模板化方法是一个完美的 __gc 方法。就像这样

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

另请参阅


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2014 年 2 月 23 日下午 5:22 GMT (差异)