问题
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