Как да синхронизирате Lua и C++ събиране на отпадъци

Опитвам се да вградя lua в съществуващо C++ приложение и съм направил стандартна процедура за него, като наследявам от клас, който върши работата. Сериозният проблем, който виждам, е, че ако откритият обект бъде премахнат или изтрит в средата на C++, тогава извикване от Lua ще причини сривове. Ако паметта се изтрива от програмата с помощта на "delete", тогава може би мога да напиша обвивка на delete, за да се погрижа и за освобождаването в Lua, но ако паметта е била разпределена от C++ и освободена, когато подходящата променлива е извън обхвата Не виждам начин как да открия това и след това да предприема подходящи действия в lua пространството, някой има ли идеи по този въпрос?

Благодаря.


person Milind    schedule 02.09.2011    source източник
comment
Когато дадете стойност на lua като потребителски данни, lua се грижи за освобождаването на паметта за този обект. Така че не трябва да извиквате delete на указател, който сте дали на lua като потребителски данни.   -  person Seth Carnegie    schedule 02.09.2011
comment
Звучи сякаш деструкторът на класа е общият метод за почистване, който търсите, тъй като се извиква, когато стеков обект излезе извън обхвата и когато извикате delete на динамично разпределен обект.   -  person Christian Rau    schedule 02.09.2011


Отговори (3)


Като цяло, почти всяка обвивка на Lua има някакъв начин да реши кой каква памет притежава. Тоест, дали даден обект е собственост на (и следователно ще бъде изтрит от) Lua или от вашето приложение.

Ако сте дали на Lua указател към обект, който C++ притежава, тогава трябва да намерите начин да гарантирате, че Lua няма да използва този указател след точката, в която C++ го изтрива. Има няколко начина да избегнете това. Един от начините е да прехвърлите собствеността на Lua.

Друг начин е да използвате boost/std::shared_ptr, което ви позволява да споделяте собствеността между C++ и Lua. Ако правите това ръчно, тогава създавате някои нелеки потребителски данни, които са с размер на shared_ptr в Lua. Прикрепяте метаметод за почистване към него, който ще унищожи shared_ptr, и използвате placement-new, за да конструирате shared_ptr на потребителските данни на Lua. Luabind всъщност има това вградено като функция: ако подадете shared_ptr към Lua, тогава и двамата споделят собствеността върху паметта.

Можете също да използвате boost/std::weak_ptr. Това е обект, към който питате, за да получите shared_ptr. Идеята е, че не трябва да държите показалеца наоколо; заявявате го временно, ако е необходимо, но съхранявате само weak_ptr за постоянно. Ако обектът е загубил всичките си shared_ptr препратки, тогава запитването към weak_ptr ще върне нулев указател.

person Nicol Bolas    schedule 02.09.2011

Ще трябва да използвате RAII обвивка, която може да се свързва с екземпляра на Lua с помощта на регистъра и да изложи стойностите на Lua с помощта на таблица - можете да премахнете вътрешен указател от него, когато сте готови.

template<typename T> class LuaExposedValue {
    T t;
    lua_State* ls;
public:
    LuaExposedValue(lua_State* L) {
        // set registry[&t] = { &t }
        ls = L;
    }
    ~LuaExposedValue() {
        // remove &t from the table
    }
}

Като алтернатива, просто забранете достъпа на Lua до него, след като променливата изчезне и оставете скриптера да се тревожи за това.

И накрая, можете просто да разпределите всичко, до което Lua има достъп, като използвате Lua GC.

person Puppy    schedule 02.09.2011

Отказ от отговорност: Написах библиотеката, която ще препоръчам

Може да искате да опитате да използвате тази LuaWrapper библиотека, която звучи така, сякаш ще се справи с това, което опитвате да направя. Това дори не е библиотека, а просто един заглавен файл.

Можете да използвате luaW_push<MyType>(L, myObj);, за да вкарате вашите обекти в Lua. Lua няма да притежава обектите, които създавате от C++, освен ако не стартирате luaW_hold<MyType> върху тях. С други думи, освен ако не кажете на Lua, тя няма да изхвърли вашия обект.

Обратно, можете да използвате MyType.new() във вашия код на Lua, за да създадете обект, който Lua притежава. Ще бъде събран боклук, както бихте очаквали. Ако искате да предадете собствеността на C++, можете да извикате luaW_release<MyType> на вашия обект.

Има и функции като luaW_to<MyType> и luaW_check<MyType> и в ограничена степен правилно поддържа наследяване от базови типове (въпреки че в момента позволява само единично наследяване). Намирам, че това значително опростява собствените ми опити да използвам C++ и Lua заедно, защото прави управлението на собствеността върху указателя много лесно.

person Alex    schedule 02.09.2011