4

我有两个 djinni 接口,一个用 Swift/objective C/javaSwiftObj实现,一个用 C++ 实现CPPObj

SwiftObj = interface +o +j {
    someSwiftMethod();
}

CPPObj = interface +c {
    static create(swiftObj: SwiftObj): CPPObj;
    someCPPMethod();
}

它们都有一个指向对方的指针,因此SwiftObj将能够调用someCPPMethod()CPPObj反之亦然:CPPObj将能够从someSwiftMethod()调用SwiftObj

迅速:

  • 类变量:var myCPPObj: SwiftObj!
  • 创作:myCPPObj = MyCPPObj.create(self)
  • 用法:myCPPObj.someCPPMethod()

在 C++ 中:

  • 类变量:shared_ptr<SwiftObj> mySwiftObj_;
  • 用法:mySwiftObj_->someSwiftMethod();

所以这里的问题是,由于循环引用,这些对象没有被垃圾收集(我尝试并删除了循环引用,他们得到了 GCed)。

但后来我尝试将其中一个指针设置为弱。在 C++ 中:weak_ptr<SwiftObj> mySwiftObj_;......但这使得mySwiftObj_它立即被 GC,即使它实际上仍然存在于 swift 中。当我将 swift 指针设置为弱而 C++ 设置为强时,同样的事情发生了。

那么我该如何处理这种情况呢?(除了手动将这些指针之一设置为空)。关于指针如何在 djinni 中实际工作的任何见解?

谢谢!

4

1 回答 1

7

不幸的是,没有一种弱引用/指针可以理解跨语言的所有权,而 Djinni 也没有尝试添加一个。C++ 和 Swift 中可用的弱语义只知道同一语言中的引用,这就是您看到即时 GC 行为的原因。它是 Djinni 生成的代理对象,它被弱持有,并且变得未使用,但是一旦代理消失,它就会释放真实的对象。

我认为最简单的方法是将 Swift 对象拆分为两个对象,我们称它们为 Owner 和 Listener。在您的示例中,只有 Listener 需要是 Djinni 对象,并实现someSwiftMethod(). 也许您还有其他原因让 Owner 也成为 Djinni 界面。如下设置您的所有权图。原谅 ASCII 艺术:Swift 在左边,C++ 在右边。

                  <- Swift|C++ ->

  SwiftOwner ------------------------> CppObj
    ^    |                               |
    |    |                               |
 (weak)  |                               |
    |    v                               |
  SwiftListener <------------------------+

在这种情况下,循环性和弱引用都仅限于 Swift,因此将按您的预期工作,并且SwiftListener可以SwiftOwner根据需要转发方法。该模型针对这些对象的外部使用来自 Swift 的情况进行了优化。此类用户应持有对SwiftOwner. 如果您的主要用途是在 C++ 中,您可以反转图片,或者您可以让外部 C++ 对象持有对 SwiftOwner 的强引用。无论哪种方式,SwiftOwner 都没有(强)循环引用,一旦它被释放,其他两个对象也将被释放。

于 2017-10-13T05:58:50.570 回答