【问题标题】:Swig: simple idiomatic wrapper usage when weak_ptr are used?Swig:使用 weak_ptr 时简单的惯用包装器用法?
【发布时间】:2021-12-19 09:43:12
【问题描述】:

注意:这个问题与weak_ptr的使用有关,但与包装weak_ptrs无关。

我目前正在评估 Swig,我发现客户端语言在使用包装器时存在“不便”,我没有在网上找到描述,也没有令人满意的解决方案。

在 C++ 中,如果您有一个使用 shared_ptrs 管理的复杂对象图,则必须特别注意该图何时可以具有循环(即,如果它不是 DAG),否则您将get memory leaks。我的意思是如果你必须(无法避免)有一个循环,它必须至少包含一个weak_ptr。这意味着您将不得不处理无法锁定weak_ptr 的情况,因为相关的shared_ptr 已经死亡。这种管理是 C++ 程序员可以用来处理的。现在让我们看看包装器的用户会发生什么:

那么我们来看下面的例子:

  • 对象 a,由一个 shared_ptr 持有,有一个 shared_ptr 到 b
  • 由 shared_ptr 持有的对象 b 与 a 有一个 weak_ptr

包装器的用户可能会发生以下情况:

A a
B b = a->GetB()
// here let's suppose that a gets out of scope, so it can be garbage collected
b->GetA() // fails if a has been garbage collected

可以通过将 C++ 异常传播到客户端代码(如果无法锁定 weak_ptr 以创建 shared_ptr,则抛出)干净地管理故障。然而,这对于 Python/C#/Java 用户来说并不习惯:他们除了必须手动保持某些对象处于活动状态才能访问其他对象。

我有一个替代解决方案的草稿,其中涉及创建对象 a 和 b 的 C++“共同所有者”,当通过包装器访问 a 或 b 中的任何一个时,SWIG 包装器将锁定该对象 a 和 b,从而保持两者当通过包装器访问它们中的任何一个时,a 和 b 还活着。缺点是这开始看起来像我在 C++ 中实现一个 proto-garbage-collection,这也修改了对象 a 和 b 的 C++ 实现和 API,最后对象 a 和 b 必须由包装器通知它们是通过包装器使用的(我认为如果不修补 SWIG 以在阴影对象的构造函数和析构函数中添加函数调用??)。

我错过了什么吗?这个问题还有其他解决方案吗?

【问题讨论】:

  • 这个问题还有其他解决方案吗? 如果问题的意思是我怎样才能让我的代码表现得好像它有垃圾收集一样,那么滚动你自己的垃圾收集是可能是要走的路。

标签: c++ garbage-collection swig weak-references weak-ptr


【解决方案1】:

公开可用的弱指针

如果弱所有权实际上是接口的一部分,则可以手动绑定表现出弱指针行为的额外类型。 In this example 他们创建了一个类型 FooWeakPtr 提供相关接口。但正如您所见,这并没有利用每种语言中特定于语言的类。

内部弱指针

如果弱指针不是接口的一部分,那么 SWIG 生成的绑定不应该关心它们,并将绑定的对象视为共享指针(至少在 Python 和 Java 中)。因此,只要您的对象在其他语言中可用,您就必须确保它们都保持活动状态。

这意味着您可以自行设计对象的层次结构,使客户端永远不会遇到内部弱指针无效的情况,并且删除每个引用实际上会导致层次结构的破坏。

解决方案实际上存在于对象层次结构的细节中,而 SWIG 对此无能为力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多