How to synchronize Lua and C ++ garbage collection

I am trying to embed lua in an existing C ++ application and made a standard procedure for it, inheriting from the class that does this work. The serious problem that I see is that if the open object is freed or deleted in the C ++ environment, then a call from Lua will fail. If the memory is deleted by the program using "delete", I can write a wrapper in delete to take care of freeing in Lua, but if the memory was allocated with C ++ and freed when the corresponding variable went out of scope, I don’t see a way to find it. and then take appropriate action in lua space, does anyone have any ideas on this?

Thanks.

+4
source share
3 answers

In general, almost every Lua shell has some way to decide who owns some kind of memory. That is, whether the object belongs (and therefore will be deleted) by Lua or your application.

If you pointed Lua to a pointer to an object belonging to C ++, then you should find a way to make sure that Lua does not use this pointer outside the point where C ++ deletes it. There are several ways to avoid this. One way is to transfer ownership of Lua.

Another way is to use boost/std::shared_ptr , which allows you to share property between C ++ and Lua. If you do this manually, then you are creating some non-light user data whose size is shared_ptr in Lua. You attach a cleanup metamethod to it that destroys shared_ptr , and you use the new location to create shared_ptr in Lua user data. Luabind really has this built-in function: if you pass shared_ptr to Lua, then they both share memory ownership.

You can also use boost/std::weak_ptr . This is the object you request to receive shared_ptr . The idea is that you should not hold the pointer; you request it as needed, but keep only weak_ptr . If the object has lost all its shared_ptr links, then a weak_ptr request will return a null pointer.

+2
source

You will need to use the RAII shell, which can communicate with the Lua instance using the registry and set the values ​​in Lua using the table - you can remove the internal pointer from it when you're done.

 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 } } 

Alternatively, simply prevent Lua from accessing it after the variable disappears, and let the scriptwriter worry about it.

Finally, you can simply highlight everything that Lua can get using the Lua GC.

+1
source

Disclaimer: I wrote a library that I want to recommend

You might want to try this LuaWrapper library, which sounds like it will handle what you are trying to do. It is not even a library, it is just one header file.

You can use luaW_push<MyType>(L, myObj); to push your objects to Lua. Lua will not be the owner of the objects you created from C ++ unless you run luaW_hold<MyType> . In other words, if you do not tell Lua, this will not cause your object to crash.

Conversely, you can use MyType.new() in your Lua code to create an object that Lua owns. This will be garbage collection, as you would expect. If you want to transfer ownership of C ++, you can call luaW_release<MyType> on your object.

There are also functions such as luaW_to<MyType> and luaW_check<MyType> , and to a limited extent it correctly supports inheritance from basic types (although at the moment it allows only one inheritance). I find that it greatly simplifies my own attempts to use C ++ and Lua together, because it makes managing the ownership pointer very easy.

+1
source

All Articles