如何同步Lua和C ++垃圾回收

时间:2011-09-02 16:28:48

标签: c++ garbage-collection lua

我正在尝试将lua嵌入到现有的C ++应用程序中,并通过从执行该工作的类继承来为其创建标准过程。       我看到的一个严重问题是,如果暴露的对象在C ++环境中被释放或删除,那么来自Lua的调用将导致崩溃。如果程序使用'delete'删除内存,那么我也可以在delete上编写一个包装器来处理Lua中的deallocation,但是如果内存是由C ++分配的,并且在适当的变量超出范围时解除分配我没有看到如何找到它然后在lua空间采取适当行动的方法,任何人对此都有任何想法?

感谢。

3 个答案:

答案 0 :(得分:2)

通常,几乎每个Lua包装器都有某种方式来决定谁拥有什么内存。也就是说,对象是由Lua还是由您的应用程序拥有(因此将被删除)。

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

另一种方法是使用boost/std::shared_ptr,它允许您在C ++和Lua之间共享所有权。如果您手动执行此操作,那么您将创建一些非轻量级用户数据,其大小为Lua中的shared_ptr。你附加了一个清理metame方法,它会破坏shared_ptr,你使用placement-new来构建Lua userdata上的shared_ptr。 Luabind实际上将此内置功能作为一项功能:如果您将shared_ptr传递给Lua,那么它们都会共享内存的所有权。

您还可以使用boost/std::weak_ptr。这是您查询以获取shared_ptr的对象。这个想法是你不应该把指针放在身边;您可以根据需要临时查询,但只能永久存储weak_ptr。如果对象丢失了所有shared_ptr引用,则查询weak_ptr将返回空指针。

答案 1 :(得分:1)

您必须使用可以使用注册表绑定到Lua实例的RAII包装器,并使用表将值公开给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可以访问的所有内容。

答案 2 :(得分:1)

免责声明:我写了我要推荐的图书馆

您可能想尝试使用此LuaWrapper库,听起来它会处理您要执行的操作。它甚至不是真正的库,它只是一个头文件。

您可以使用luaW_push<MyType>(L, myObj);将对象推送到Lua。除非你对它们运行luaW_hold<MyType>,否则Lua不会拥有你用C ++创建的对象。换句话说,除非你告诉Lua,否则它不会垃圾收集你的对象。

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

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