gpt4 book ai didi

c++ - 使用 C++ 库的 Swift 中的 takeRetainedValue() 或 takeUnretainedValue()

转载 作者:太空宇宙 更新时间:2023-11-04 07:54:30 25 4
gpt4 key购买 nike

我正在开发一个 Swift 项目,该项目使用封装在 C++ 中的 C 库。

  • 该库为您提供了同步和异步获取/设置变量的可能性。

  • 库作为回调方法通知何时甚至已经发生。

我在 swift 中有这个功能:

/*** Convert const void* To Any T ***/

func bridgeToTypeRetained<T : AnyObject>(ptr : UnsafeMutableRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}

func bridgeToTypeUnretained<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}

/*** Convert const void* To Any T ***/
func bridgeToPointerRetained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
}

func bridgeToPointerUnretained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}

为了从库中实现回调,在库中我有以下定义:

DllExport void STDCALL CpProxyAvOpenhomeOrgInfo1SetPropertyTrackCountChanged(THandle aHandle, OhNetCallback aCallback, void* aPtr);

typedef void (STDCALL *OhNetCallback)(void* aPtr);

然后我 swift 使用以下代码:

 CpProxyAvOpenhomeOrgInfo1SetPropertyTrackCountChanged(myHandle, { (pointer) in

if pointer != nil{
let myClass:MyClass = bridgeToTypeRetained(ptr: pointer!)
myClass.aValu = 0 //CRASH BAD ACCESS
let myClass:MyClass = bridgeToTypeUnretained(ptr: pointer!)
myClass.aValu = 0 //NO CRASH
}

}, bridgeToPointerRetained(obj: self))

为了实现异步操作,在库中我有以下定义:

DllExport void STDCALL CpProxyAvOpenhomeOrgInfo1BeginCounters(THandle aHandle, OhNetCallbackAsync aCallback, void* aPtr);

typedef void (STDCALL *OhNetCallbackAsync)(void* aPtr, OhNetHandleAsync aAsync);

然后swift我使用下面的代码

    let classCallback = ClassCallback()
classCallback.classObject = self

CpProxyAvOpenhomeOrgInfo1BeginCounters(prxHandleId, { (pointer, ohNetAsync) in

if pointer != nil && ohNetAsync != nil{

let classCallback : ClassCallback = bridgeToTypeRetained(ptr: pointer!)
classCallback.classObject.aValue = 1 //NO CRASH

}


}, bridgeToPointerRetained(obj: classCallback))

所以我的问题是:

  • 根据我从 C++ 库中获得的信息,我什么时候必须使用 takeRetainedValue() 或 takeUnretainedValue()?

谢谢。

最佳答案

如果你希望你的 ClassCallback 存在,即使你对它的所有 Swift 引用都消失了,你需要传递一个保留值,这会在没有添加适当的清理逻辑的情况下造成内存泄漏。如果你传递一个未保留的值,那么当你试图取回你的 ClassCallback 时,如果你所有的 swift 引用都消失了,你将会崩溃。

在您的回调中,您可以使用一个未保留的引用来获取该对象,假设您希望它在范围结束时继续存在且其当前引用计数。如果您采用保留引用,引用计数将减少并销毁该对象(如果这是最后一个引用)。

我通常做的是传入一个保留引用并获取一个非保留引用,直到我准备好处理回调对象。当发生这种情况时,我会使用上下文指针的保留值(在您的情况下为 aPtr)来平衡保留的传递并将其替换为新的适当值。

关于c++ - 使用 C++ 库的 Swift 中的 takeRetainedValue() 或 takeUnretainedValue(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51171787/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com