我将我的应用程序的内部暴露给Lua,通过luabind,在c++中,我有shared_ptr<Item>
的Container
,其中Item
是一个抽象基类。衍生类包括ItemA
和ItemB
。
为了将这些暴露给luabind,我使用了两个包装器类(因为我希望容器在脚本接口中具有不同的编辑机制)。我希望能够枚举项目在一个Lua脚本中的容器像这样:
container=app.container
for i,event in ipairs(container.items) do
print(tostring(event))
end
我遇到的问题是,我可以通过向ItemWrappers
返回原始指针来暴露此功能,但这会导致内存泄漏,因为ItemWrapper
析构函数从未被调用。如果我尝试将luabind中的包装器声明为文档中描述的智能指针,那么当我尝试将智能指针作为lua对象返回时,会抛出'试图使用未注册的类'异常。
包装器的定义如下:
class ContainerWrapper {
public:
ContainerWrapper(Container& c) : container(c) {};
Container& c; // reference to the actual container
};
class ItemWrapper {
public:
virtual ~ItemWrapper() {};
ItemWrapper(int itemIndex_) : itemIndex(itemIndex_) {};
int itemIndex; // items are addressed by index
};
class ItemAWrapper : public ItemWrapper {
public:
ItemAWrapper(int itemIndex_) : ItemWrapper(itemIndex_) {};
};
luabind注册看起来像这样:(如果我不使用智能指针)
class_<ItemWrapper>("Item") ,
class_<ItemAWrapper, ItemWrapper>("ItemA")
,像这样,如果我这样做:
class_<ItemWrapper, std::tr1::shared_ptr<ItemWrapper> >("Item") ,
class_<ItemAWrapper, ItemWrapper, std::tr1::shared_ptr<ItemWrapper> >("ItemA")
公开Container
的items
成员的函数返回一个lua表:
luabind::object Container::getItemsAsTable(lua_State* L)
{
luabind::object table=luabind::newtable(L);
for (int i=0; i<items.size(); i++) {
table[i+1]= new ItemAWrapper(); // or function to return pointer/smart pointer
}
return table;
}
这是在表中设置值的正确方法吗?如果我传递一个智能指针,它是生成异常的赋值,但如果我传递一个原始指针,那么它似乎不会在内部将其赋值给智能指针,对象就会泄露。做垃圾收集也没有帮助。
Lua已经是多态的了。所以你的getItemsAsTable
函数不需要new
这些ItemWrapper
对象。只要把价值观放在里面。像这样:table[i+1] = ItemAWrapper()
。除非在某些情况下需要使用指针(例如更改Lua表应该在c++中反映),否则不要麻烦。