Swift 3 - 如何通过UnsafeMutableRawPointer传递结构体的引用?

3
在“核心音频(Core Audio)”框架中,可以通过使用“UnsafeMutableRawPointer?”将用户数据传递到回调函数中。我在思考如何通过这个“UnsafeMutableRawPointer?”以引用的方式传递结构体。在回调函数内部进行的更改应该在回调函数外部反映出来。
我设置了一个游乐场来测试这个问题:
struct TestStruct {
    var prop1: UInt32
    var prop2: Float64
    var prop3: Bool
}

func printTestStruct(prefix: String, data: TestStruct) {
    print("\(prefix): prop1: \(data.prop1), prop2: \(data.prop2), prop3: \(data.prop3)")
}

func testUnsafeMutablePointer(data: UnsafeMutableRawPointer?) {
    var testStructInFunc = data!.load(as: TestStruct.self)

    printTestStruct(prefix: "In func (pre change)", data: testStructInFunc)

    testStructInFunc.prop1 = 24
    testStructInFunc.prop2 = 1.2
    testStructInFunc.prop3 = false

    printTestStruct(prefix: "In func (post change)", data: testStructInFunc)
}

var testStruct: TestStruct = TestStruct(prop1: 12, prop2: 2.4, prop3: true)

printTestStruct(prefix: "Before call", data: testStruct)

testUnsafeMutablePointer(data: &testStruct)

printTestStruct(prefix: "After call", data: testStruct)

可悲的是,似乎在testUnsafeMutablePointer函数中对testStruct所做的任何更改都会在函数调用后丢失。

我以为UnsafeMutableRawPointer在这里的行为类似于按引用传递?我错过了什么吗?

1个回答

3
你的函数将数据复制到本地结构体中,但没有将修改后的数据复制回去。因此,在你的特殊情况下,这可能是一种解决方案:
func testUnsafeMutablePointer(data: UnsafeMutableRawPointer?) {
    var testStructInFunc = data!.load(as: TestStruct.self)

    testStructInFunc.prop1 = 24
    testStructInFunc.prop2 = 1.2
    testStructInFunc.prop3 = false

    data!.storeBytes(of: testStructInFunc, as: TestStruct.self)
}

但请注意,这仅适用于结构体仅包含像整数和浮点数等“简单”值的情况。像数组或字符串这样的“复杂”类型包含对实际存储的不透明指针,不能像这样简单地复制。

另一种选择是像这样修改所指向的结构体:

func testUnsafeMutablePointer(data: UnsafeMutableRawPointer?) {
    let testStructPtr = data!.assumingMemoryBound(to: TestStruct.self)

    testStructPtr.pointee.prop1 = 24
    testStructPtr.pointee.prop2 = 1.2
    testStructPtr.pointee.prop3 = false
}

两种解决方案都假设当回调被调用时,结构体仍然存在,因为传递指针并不能确保指向的结构体的生存期。作为替代方案,请考虑使用一个类的实例。传递保留或未保留的指向该实例的指针允许在回调“活动”时控制对象的生命周期,可参考如何在Swift中将self转换为UnsafeMutablePointer<Void>类型

非常感谢!这确实为我解决了问题。在这里,最_swifty_的解决方案是什么(我假设使用class,但我对__Swift__还很陌生)? - user6105890
@Herickson:没有更多的上下文很难说。你正在与C API交互,所以无论如何都不会有纯Swift。 - Martin R

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