dastrobu
dastrobu

Reputation: 1726

How to invoke a mutating method on an unsafe pointer in Swift?

Having a struct with a mutating method I can pass an instance of a struct as inout parameter and call the method. The passed instance will be modified like shown in the example below.

struct S{
    var i = 0
    mutating func incI(){ i += 1}
}
func f(s: inout S){
    s.incI()
}

var s = S()

print(s) // prints S(i: 0)
f(s: &s)
print(s) // prints S(i: 1)

When interacting with C APIs one often gets just an unsafe pointer. My question is, how can I call the mutating function on the pointee and thereby modify the original instance.

fun f(p: UnsafeMutableRawPointer){
    var s = p.assumingMemoryBound(to: S.self).pointee // could also use p.load(as: S.self) with same effect
    s.incI()
    print(s) // prints S(i: 1)
}

s = S()
print(s) // prints S(i: 0)
f(p: &s)
print(s) // prints S(i: 0) but want it to print S(i: 1)

The example indicates that somehow a copy of the instance is made. This behaviour is not only unexpected but also leaves me aimless on how to mutate the memory backing the pointer.

Upvotes: 1

Views: 230

Answers (1)

Martin R
Martin R

Reputation: 539685

The problem is not how you call the function, that part is correct.

But your function f (which apparently is meant to simulate the behavior of a C function) mutates a local copy. If you change the function to

func f(p: UnsafeMutableRawPointer){
    let sPtr = p.assumingMemoryBound(to: S.self)
    sPtr.pointee.incI()
}

then everything works as expected:

var s = S()
print(s) // prints S(i: 0)
f(p: &s)
print(s) // prints S(i: 1)

Upvotes: 1

Related Questions