ios — djinni — указатели и циклические ссылки между C ++ и swift / target C / java

У меня есть два интерфейса Джинни, один из которых будет реализован в Swift / Objective C / Java SwiftObj и один будет реализован в 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()

В с ++:

  • переменная класса: shared_ptr<SwiftObj> mySwiftObj_;
  • Использование: mySwiftObj_->someSwiftMethod();

Таким образом, вопрос здесь заключается в том, что эти объекты не собирают мусор из-за циклической ссылки (я попытался удалить циклическую ссылку, и они получили GCed).

Но затем я попытался установить один из этих указателей как слабый. В C ++: weak_ptr<SwiftObj> mySwiftObj_; … но это сделало mySwiftObj_ Быть GCed мгновенно, даже когда он на самом деле все еще существует в быстрой. То же самое произошло, когда я установил слабый указатель swift и сильный C ++.

Так как я могу справиться с этой ситуацией? (кроме ручной установки одного из этих указателей как ноль). Есть идеи о том, как на самом деле работают указатели в джиннах?

Спасибо!

4

Решение

К сожалению, нет какой-либо слабой ссылки / указателя, которая может понимать владение разными языками, и Джинни не пытается добавить его. Доступная слабая семантика в C ++ и Swift знает только о ссылках в одном и том же языке, поэтому вы видите мгновенное поведение GC. Это сгенерированный Джинни прокси-объект, который слабо удерживается и становится неиспользованным, но как только прокси исчезает, он освобождает реальный объект.

Я думаю, что самым простым подходом было бы разделить объект Swift на два объекта, назовем их Owner и Listener. В вашем примере только Listener должен быть объектом Djinni и реализовывать someSwiftMethod(), Возможно, у вас есть и другие причины, по которым владелец должен быть интерфейсом Джинни. Настройте свой график владения следующим образом. Простите за искусство ASCII: Свифт слева, С ++ справа.

                  <- Swift|C++ ->

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

В этом сценарии круговые и слабые реферы ограничены Swift, поэтому будут работать так, как вы ожидаете, и SwiftListener может пересылать по методам SwiftOwner как необходимо. Эта модель оптимизирована для случая, когда внешнее использование этих объектов исходит от Swift. Такие пользователи должны иметь ссылку на SwiftOwner, Если вы в основном используете C ++, вы можете изменить картину или сделать так, чтобы внешние объекты C ++ содержали сильную ссылку на SwiftOwner. В любом случае, SwiftOwner не имеет (сильных) циклических ссылок на него, и как только он будет выпущен, будут выпущены и другие два объекта.

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]