3

Core Audio-Framework 中,用户数据可以通过UnsafeMutableRawPointer?. 我想知道如何通过 this通过引用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)

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

我在想,UnsafeMutableRawPointer这里的行为就像通过引用传递?我错过了什么?

4

1 回答 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
}

两种解决方案都假定调用回调时结构仍然存在,因为传递指针并不能确保指向的结构的生命周期。

作为替代方案,请考虑使用 a 的实例class。将保留或未保留的指针传递给实例允许在回调“活动”时控制对象的生命周期,比较 如何将 self 转换为 swift 中的 UnsafeMutablePointer<Void> 类型

于 2017-03-04T13:09:55.227 回答