在 C++ 中,假设我有一个类可以创建类似二叉树的结构,我使用它是这样的:
CTreeRoot* root = new CTreeRoot(/* whatever */);
CNode* leftNode = root->getLeftNode();
CNode* rightNode = root->getRightNOde();
leftNode->doSomething();
rightNode->doSomething();
// etc
并假设左右节点有自己的左右节点(因此,二叉树)。现在我想把它暴露给 Lua(不使用 luabind),所以我可以做同样的事情:
local root = treeroot.new(/* whatever */)
local left = root:getLeftNode()
local right = root:getRightNode()
left:doSomething();
right:doSomething();
我已经完成了大部分工作。但是,对于 getLeftNode() 和 getRightNode() 方法,我很确定我做错了。以下是我在 C++ 中实现 getLeftNode() 的方式,例如:
int MyLua::TreeRootGetLeftNode(luaState* L)
{
CTreeRoot* root = (CTreeRoot*)luaL_checkudata(L, 1, "MyLua.treeroot");
CNode* leftNode = root->getLeftNode();
if (leftNode != NULL)
{
int size = sizeof(CNode);
// create a new copy of the CNode object inplace of the memory Lua
// allocated for us
new ((CNode*)lua_newuserdata(L,size)) CNode((const CNode&)*leftNode);
lua_setmetatable(L, "MyLua.treenode");
}
else
{
lua_pushnil(L);
}
return 1;
}
我将 userdata 转换回 CTreeRoot 对象,调用 getLeftNode(),确保它存在,然后(这里是“错误的部分”)创建另一个 userdata 数据对象,并使用复制构造函数复制我想要返回的对象。
这是这种情况的“标准做法”吗?似乎您希望避免创建对象的另一个副本,因为您真正想要的只是对已经存在的对象的引用。
听起来这将是 lightuserdata 的理想场所,因为我不想创建新对象,我很乐意返回已经存在的对象。但是,问题是 lightuserdata 没有元表,所以一旦我把它们拿回来,这些对象对我来说就毫无用处了。基本上,我想做类似的事情:
int MyLua::TreeRootGetLeftNode(luaState* L)
{
CTreeRoot* root = (CTreeRoot*)luaL_checkudata(L, 1, "MyLua.treeroot");
CNode* leftNode = root->getLeftNode();
if (leftNode != NULL)
{
// "WRONG" CODE BUT SHOWS WHAT I WISH I COULD DO
lua_pushlightuserdata(L, (void*)leftNode);
lua_setmetatable(L, "MyLua.treenode");
}
else
{
lua_pushnil(L);
}
return 1;
}
有人可以告诉我如何让我的MyLua::TreeRootGetLeftNode
方法将已经存在的对象的副本返回给 Lua,以便我可以将该对象用作 Lua 中的“对象”吗?