c++ - Swig:使用 weak_ptr 时的简单惯用包装器用法?
问题描述
注意:这个问题与weak_ptr 的使用有关,但与包装weak_ptr 无关。
我目前正在评估 Swig,我发现客户端语言在使用包装器时存在“不便”,我没有在网上找到描述,也没有令人满意的解决方案。
在 C++ 中,如果您有一个使用 shared_ptrs 管理的复杂对象图,则必须特别注意该图何时可以具有循环(即,如果它不是 DAG),否则您将出现内存泄漏。我的意思是如果你必须(不能避免)有一个循环,它必须至少包含一个weak_ptr。这意味着您将不得不处理无法锁定weak_ptr 的情况,因为相关的shared_ptr 已经死亡。这种管理是 C++ 程序员可以用来处理的。现在让我们看看包装器的用户会发生什么:
所以让我们看下面的例子:
- 由 shared_ptr 持有的对象 a 与 b 有一个 shared_ptr
- 由 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当通过包装器访问它们中的任何一个时,它们还活着。缺点是这开始看起来像是我在 C++ 中实现了一个 proto-garbage-collection,这也修改了对象 a 和 b 的 C++ 实现和 API,最后对象 a 和 b 必须由包装器通知它们是通过包装器使用的(我认为如果不修补 SWIG 以在阴影对象的构造函数和析构函数中添加函数调用??)。
我错过了什么吗?这个问题还有其他解决方案吗?
解决方案
公开可用的弱指针
如果弱所有权实际上是接口的一部分,则可以手动绑定表现出弱指针行为的额外类型。在这个例子中,他们创建了一个FooWeakPtr
提供相关接口的类型。但正如您所看到的,这并没有利用每种语言中特定于语言的类。
内部弱指针
如果弱指针不是接口的一部分,那么 SWIG 生成的绑定不应该关心它们,并将绑定的对象视为共享指针(至少在 Python 和 Java 中)。因此,只要您的对象可以从其他语言获得,您就必须确保它们都保持活跃。
这意味着由您来设计对象的层次结构,使客户端永远不会遇到内部弱指针无效的情况,并且删除每个引用实际上会导致层次结构的破坏。
解决方案实际上存在于对象层次结构的细节中,而 SWIG 对此无能为力。
推荐阅读
- c# - 如何在运行时连接到 Office fluent 功能区并在 C# 中添加/操作功能区选项卡?
- nginx - 使用 certbot 设置 ufw 和 HTTP,我不能再使用 SFTP
- python - 替代 django-crispy-forms
- javascript - Flipswitch - 如何将翻转开关状态存储在变量中?
- linux - 从 cron 作业运行 bash 脚本
- python - 范围不是我在使用 Pandas 时所期望的
- javascript - 如何从 javascript 中的 BigInt 获取数字?
- spring - 在 IntelliJ IDEA 错误中导入项目 spring-boot
- java - 如果初始文本以换行符结尾,如何防止 JTextPane 重置字体设置?
- javascript - 未设置状态的属性 [“此字段是必需的。”]