Djinni - C++、Swift/Objective C和Java之间的指针和循环引用

4

我有两个djinni接口,一个要在Swift/Objective C/Java中实现SwiftObj,另一个要在C++中实现CPPObj

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

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

他们相互引用,所以SwiftObj将能够调用CPPObjsomeCPPMethod()方法,反之亦然:CPPObj将能够从SwiftObj调用someSwiftMethod()方法:

在 Swift 中:

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

在 C++ 中:

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

所以问题是,由于循环引用,这些对象不会被垃圾回收(我尝试过并删除了循环引用,它们被垃圾回收了)。

但是我尝试将其中一个指针设置为弱引用。在 C++ 中:weak_ptr<SwiftObj> mySwiftObj_; ... 但这使得mySwiftObj_立即被垃圾回收,即使它实际上仍存在于 Swift 中。当我将 Swift 指针设置为弱引用并将 C++ 设置为强引用时,同样的事情也发生了。

那么我该如何处理这种情况?(除了手动将其中一个指针设置为 null)。对于指针在 djinni 中实际工作方式的任何见解都会有所帮助。

谢谢!


问题不在于它们在djinni中如何工作,因为djinni根本没有指针。你的问题可能是你不知道C++中智能指针的工作原理。我说得对吗? - skypjack
不。如果全部都是C++,将A设置为强引用指向B,同时将B设置为弱引用指向A可以解决循环指针问题。但由于djinni处于中间位置,如果我有一个弱引用指向它,那么它会立即被垃圾回收。 - Martin Massera
Djinni不会返回弱指针,是你将其返回的共享指针分配给了一个弱指针。你知道吗? - skypjack
我知道并且已经尝试过了。请阅读帖子。 - Martin Massera
我已经阅读了这篇文章并且确实在评论它。只是指出你没有正确地使用智能指针这一事实。 - skypjack
我不认为你做错了。跨语言使用弱引用的语义确实是一个难题。请看下面更详细的回答。 - Andrew
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没有(强)循环引用,一旦它被释放,另外两个对象也会被释放。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接