Я представляю внутренности моего приложения Lua через luabind, где в C ++ у меня есть Container
из shared_ptr<Item>
где 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")
Функция выставить items
член Container
возвращает таблицу 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;
}
Это правильный способ установки значения в таблице? Это присваивание генерирует исключение, если я передаю умный указатель, но если я передаю необработанный указатель, то кажется, что он не присваивает его внутреннему умному указателю, и объект пропускается. Сбор мусора тоже не помогает.
Луа уже полиморфный. Так что ваши getItemsAsTable
функция не должна new
эти ItemWrapper
объекты. Просто вставьте в это ценности. Как это: table[i+1] = ItemAWrapper()
, Если что-то не происходит, где вы необходимость использовать указатель (например, если изменение таблицы Lua должно быть отражено в C ++), не беспокойтесь. Просто используйте значение.
Других решений пока нет …