Как вызвать мутирующий метод для небезопасного указателя в Swift?

Имея структуру с мутирующим методом, я могу передать экземпляр структуры в качестве входного параметра и вызвать метод. Переданный экземпляр будет изменен, как показано в примере ниже.

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)

При взаимодействии с C API часто получается просто небезопасный указатель. Мой вопрос в том, как я могу вызвать мутирующую функцию для указателя и тем самым изменить исходный экземпляр.

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)

В примере показано, что каким-то образом создается копия экземпляра. Такое поведение не только неожиданно, но и не дает мне понять, как изменить память, поддерживающую указатель.


person dastrobu    schedule 30.03.2020    source источник


Ответы (1)


Проблема не в том, как вы вызываете функцию, эта часть верна.

Но ваша функция f (которая, по-видимому, предназначена для имитации поведения функции C) изменяет локальную копию. Если вы измените функцию на

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

тогда все работает как положено:

var s = S()
print(s) // prints S(i: 0)
f(p: &s)
print(s) // prints S(i: 1)
person Martin R    schedule 30.03.2020