自己动手 Cpp 绑定 |
|
以下是一些我发现的技巧,主要以代码形式呈现,它们共同工作。
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; }
了解一下
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
!
看看这个
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);