在 luabind 中返回指向派生对象的指针时,可能会出现泄漏或“未注册类”的问题。

我通过 luabind 将我的应用程序的内部暴露给 Lua,在 C++ 中我有一个具有 shared_ptr<Item>Container,其中 Item 是一个抽象基类。派生类包括 ItemAItemB

为了使这些项目暴露给 luabind,我使用了几个包装类(因为我希望容器在脚本界面中具有不同的编辑机制)。我希望能够在 Lua 脚本中枚举容器中的项,如下所示:

container=app.container
for i,event in ipairs(container.items) do
  print(tostring(event))
end

我的问题是,我可以通过返回指向 ItemWrapper 的原始指针来公开此功能,但这会导致内存泄漏,因为 ItemWrapper 析构函数从未被调用。如果我试图在 luabind 中声明包装器作为智能指针 如文档中所述,那么当我尝试将智能指针作为 lua 对象返回时,就会抛出 'Trying to use unregistered class' 异常。

包装器的定义如下:

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")

暴露 Containeritems 成员的函数返回一个 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;
 }

这是在表中设置值的正确方式吗?如果我传递智能指针,则这会生成异常,但如果我传递原始指针,则似乎不会将其分配到智能指针中,并且对象将泄漏。进行垃圾回收也没有帮助。

点赞
用户734069
用户734069

Lua 已经是多态的了。所以你的 getItemsAsTable 函数不需要 new 这些 ItemWrapper 对象。只需要把值放进去就可以了。像这样:table[i+1] = ItemAWrapper()。除非有什么特殊情况需要使用指针(比如改变 Lua 表应该反映在 C++ 中),否则不要费心思,直接使用值就可以了。

2013-03-20 14:28:59