In lua is there a way to bind an upvalue to a userdata value instead of a function?
在以下示例中,将创建类型为
在理想的世界中-我希望通过这个问题来揭示-有没有一种方法可以将upvalue与值(例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using FuncArray = std::vector<const ::luaL_Reg>; static const FuncArray funcs = { {"__tostring", LI_MyType__tostring }, }; int LC_MyType_newInstance(lua_State* L) { auto userdata = static_cast<MyType*>(lua_newuserdata(L, sizeof(MyType))); new(userdata) MyType(); // Create the metatable lua_createtable(L, 0, funcs.size()); // |userdata|table| lua_pushvalue(L, -2); // |userdata|table|userdata| luaL_setfuncs(L, funcs.data(), 1); // |userdata|table| lua_setmetatable(L, -2); // |userdata| return 1; } int LI_MyType__tostring(lua_State* L) { // NOTE: Blindly assume that upvalue 1 is my userdata const auto n = lua_upvalueindex(1); lua_pushvalue(L, n); // |userdata| auto myTypeInst = static_cast<MyType*>(lua_touserdata(L, -1)); lua_pushstring(L, myTypeInst->str()); // |userdata|string| return 1; // |userdata|string| } |
我希望有一种执行类似(这是伪代码!)的方法:
1 2 3 4 5 6 7 8 9 10 | // Assume that arg 1 is userdata int LI_MyType__tostring(lua_State* L) { const int stackPosition = -1; const int upvalueIndex = 1; const auto n = lua_get_USERDATA_upvalue(L, stackPosition, upvalueIndex); lua_pushvalue(L, n); // |userdata| auto myTypeInst = static_cast<MyType*>(lua_touserdata(L, -1)); lua_pushstring(L, myTypeInst->str()); // |userdata|string| return 1; // |userdata|string| } |
我知道这类似于OOP的" normal "元表样式的情况,但是我想保持事物基于闭包并且避免引入冒号语法。
问这个问题的另一种方式是,是否有一种方法可以在使用基于闭包的OOP时在
更新(2013-10-10):基于@lhf \\使用
因此:
- 升值方法从未在元方法中使用
- 升值仅在值的实例方法中使用
- 给定类的每个实例只有一个额外的表
仍然无法避免为每个用户数据创建方法/属性表,但是这种开销是正常的。如果
(我正在跳过C代码并回答标题中的问题。)
出于某些原因,我认为您不应该尝试完全做到这一点。
只需从插槽1中获取对象,并检查其类型是否与您的userdata相匹配。 (luaL_checkudata)
例如,如果它不是对象并且调用了tostring,则只需输出其一个对象名称类,而不是实例详细信息即可。这更有意义,并且如果对象报告其实际状态,则可能会使调试更简单,而不是试图变得太聪明和误导您。