djinni - C++和swift/objective C/java之间的指针和循环引用

Mar*_*era 4 c++ objective-c ios swift djinni

我有两个djinni接口,一个用Swift/objective C/java实现SwiftObj,另一个用C++实现CPPObj.

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

CPPObj = interface +c {
    static create(swiftObj: SwiftObj): CPPObj;
    someCPPMethod();
}
Run Code Online (Sandbox Code Playgroud)

他们都有一个指向对方,所以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++设置为强时,同样的事情发生了.

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

谢谢!

atw*_*man 7

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

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

                  <- Swift|C++ ->

  SwiftOwner ------------------------> CppObj
    ^    |                               |
    |    |                               |
 (weak)  |                               |
    |    v                               |
  SwiftListener <------------------------+
Run Code Online (Sandbox Code Playgroud)

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