Я открываю внутреннее устройство своего приложения 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 как интеллектуальные указатели , как описано в docs , то это вызывает исключение «Попытка использовать незарегистрированный класс» , когда я пытаюсь вернуть умный указатель как объект 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;
}
Это правильный способ установки значения в таблице? Это назначение, которое генерирует исключение, если я передаю интеллектуальный указатель, но если я передаю необработанный указатель, он, похоже, не назначает его интеллектуальному указателю внутри, и объект утекает. Сборка мусора тоже не помогает.
1 ответ
Lua уже полиморфен. Таким образом, вашей функции getItemsAsTable
не нужно new
эти ItemWrapper
объекты. Просто придерживайтесь ценностей. Как это: table[i+1] = ItemAWrapper()
. Если что-то не происходит там, где вам нужно использовать указатель (например, если изменение таблицы Lua должно быть отражено в C ++), не беспокойтесь. Просто используйте значение.
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.
luabind::object
?luabind::object(L, ItemWrapper())