c++ - Swig:使用weak_ptr时简单的惯用包装器用法?

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

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

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

在 C++ 中,如果您有一个使用共享指针管理的复杂对象图,则当该图可以有循环时(即,如果它不是 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++ 中实现原始垃圾收集,这也修改了对象 a 和 b 的 C++ 实现和 API,最后对象 a 和 b 必须由包装器通知:它们是通过包装器使用的(我认为如果不修补 SWIG 以在影子对象的构造函数和析构函数中添加函数调用就无法做到这一点??)。

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

最佳答案

公开可用的弱指针

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

内部弱指针

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

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

解决方案实际上驻留在对象层次结构的详细信息中,SWIG 对此无能为力。

关于c++ - Swig:使用weak_ptr时简单的惯用包装器用法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69851487/

相关文章:

c++ - 为什么 new 表达式可以正确生成指针类型,即使它应该返回 void*?

web-services - 在长期运行的Common Lisp应用程序中,应使用什么策略来管理垃圾?

Python swig - 从 ctypes 指针创建 swig 包装实例

c++ - 包装和使用返回带有 SWIG 结构的函数的问题(python)

c++ - SWIG:std/multimap.i 似乎因 Tcl 包装而损坏

c++ - 为什么找到 f1 但找不到 f2?

c++ - C 字符串 :\n & ' ' not detected

c++ - 使用 C++ 获取本地计算机所属的 OU(组织单位)名称

java - 你能在 Java 中获得基本的 GC 统计信息吗?

python - 何时在 PySide 中设置父级