如何同步Lua和c++的垃圾收集

How to sync Lua and C++ garbage collection

本文关键字:c++ Lua 何同步 同步      更新时间:2023-10-16

我正试图将lua嵌入到现有的c++应用程序中,并通过继承一个做这项工作的类为它制定了一个标准过程。我看到的严重问题是,如果暴露的对象在c++环境中被释放或删除,那么来自Lua的调用将导致崩溃。如果内存被删除的程序使用"删除",那么我可以写一个包装器删除,以照顾在Lua的释放,以及,但如果内存是由c++分配和释放时,适当的变量超出了范围,我不知道如何找到,然后在Lua空间采取适当的行动,有人对此有任何想法吗?

谢谢。

一般来说,实际上每个Lua包装器都有一些方法来决定谁拥有什么内存。也就是说,一个对象是由Lua还是由你的应用程序拥有(因此将被删除)。

如果你给Lua一个指向c++拥有的对象的指针,那么你必须找到一种方法来确保Lua不会使用这个指针超过c++删除它的点。有几种方法可以避免这种情况。一种方法是将所有权转让给Lua。

另一种方法是使用boost/std::shared_ptr,它允许您在c++和Lua之间共享所有权。如果您手动执行此操作,那么您将创建一些非轻用户数据,这是Lua中shared_ptr的大小。您为它附加了一个清理元方法,它将销毁shared_ptr,并且您使用placementnew在Lua用户数据上构造shared_ptr。Luabind实际上有这个内置特性:如果你传递一个shared_ptr给Lua,那么它们都共享内存的所有权。

您也可以使用boost/std::weak_ptr。这是一个您查询以获得shared_ptr的对象。这个想法是,你不应该一直保持指针;您可以根据需要临时查询它,但是您只永久存储weak_ptr。如果对象丢失了所有的shared_ptr引用,那么查询weak_ptr将返回一个空指针。

您必须使用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 GC分配Lua可以访问的所有内容。

免责声明:我编写了我要推荐的库

你可能想尝试使用这个LuaWrapper库,听起来它会处理你正在尝试做的事情。它甚至不是一个真正的库,它只是一个头文件。

您可以使用luaW_push<MyType>(L, myObj);将您的对象推入Lua。Lua不会拥有你从c++创建的对象,除非你在它们上面运行luaW_hold<MyType>。换句话说,除非您告诉Lua这样做,否则它不会对您的对象进行垃圾回收。

相反,您可以在Lua代码中使用MyType.new()来创建一个对象,该对象由Lua 拥有。正如您所期望的那样,它将被垃圾收集。如果你想把所有权传递给c++,你可以在你的对象上调用luaW_release<MyType>

也有像luaW_to<MyType>luaW_check<MyType>这样的函数,在一定程度上它正确地支持从基类型继承(尽管目前它只允许单继承)。我发现这极大地简化了我自己同时使用c++和Lua的尝试,因为它使管理指针所有权变得非常简单。