У меня есть два интерфейса Джинни, один из которых будет реализован в 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 ++.
Так как я могу справиться с этой ситуацией? (кроме ручной установки одного из этих указателей как ноль). Есть идеи о том, как на самом деле работают указатели в джиннах?
Спасибо!
К сожалению, нет какой-либо слабой ссылки / указателя, которая может понимать владение разными языками, и Джинни не пытается добавить его. Доступная слабая семантика в 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 не имеет (сильных) циклических ссылок на него, и как только он будет выпущен, будут выпущены и другие два объекта.
Других решений пока нет …