首页 > 解决方案 > Swig:使用 weak_ptr 时的简单惯用包装器用法?

问题描述

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

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

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

所以让我们看下面的例子:

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

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当通过包装器访问它们中的任何一个时,它们还活着。缺点是这开始看起来像是我在 C++ 中实现了一个 proto-garbage-collection,这也修改了对象 a 和 b 的 C++ 实现和 API,最后对象 a 和 b 必须由包装器通知它们是通过包装器使用的(我认为如果不修补 SWIG 以在阴影对象的构造函数和析构函数中添加函数调用??)。

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

标签: c++garbage-collectionswigweak-referencesweak-ptr

解决方案


公开可用的弱指针

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

内部弱指针

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

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

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


推荐阅读