Swift 3 - Pass struct by reference via UnsafeMutableRawPointer?

孤人 提交于 2020-01-04 07:51:49

问题


In the Core Audio-Framework user data can be passed into callbacks via an UnsafeMutableRawPointer?. I was wondering how to pass a struct by reference via this UnsafeMutableRawPointer?. Changes made inside the callback should be reflected outside the callback.

I set up a playground to test this:

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)

Sadly it seems like any changes to testStruct made inside the testUnsafeMutablePointer function are lost after the function call.

I was thinking, that the UnsafeMutableRawPointer behaves like a pass by reference here? What am I missing out?


回答1:


Your function copies the data into a local struct, but does not copy the modified data back. So this would be a possible solution in your special case:

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)
}

But note that this works only if the struct contains only "simple" values likes integers and floating point values. "Complex" types like arrays or strings contain opaque pointers to the actual storage and cannot be simply copied like this.

Another option is to modify the pointed-to struct like this:

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

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

Both solutions assume that the struct still exists when the callback is called, since passing a pointer around does not ensure the lifetime of the pointed-to struct.

As an alternative, consider to use an instance of a class instead. Passing retained or unretained pointers to the instance allows to control the lifetime of the object while the callback is "active", compare How to cast self to UnsafeMutablePointer<Void> type in swift.



来源:https://stackoverflow.com/questions/42596246/swift-3-pass-struct-by-reference-via-unsafemutablerawpointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!