在C++,說我有一個創建一個二叉樹狀結構的一類,我用它是這樣的:回到已有的C++對象到Lua
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;
}
投的用戶數據回CTreeRoot對象,調用getLeftNode(),請確保它的存在,然後(這裏是「錯誤的部分」 )我用複製構造函數創建另一個用戶數據數據對象,複製我想返回的對象。
這是這種類型場景的「標準做法」嗎?看起來你想避免創建對象的另一個副本,因爲你真正想要的只是對已經存在的對象的引用。
這聽起來像這將是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中的「對象」?