Как вызвать мутационный метод на небезопасном указателе в Swift? - PullRequest
1 голос
/ 30 марта 2020

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

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 часто появляется просто небезопасный указатель. У меня вопрос, как я могу вызвать мутантную функцию в pointee и тем самым изменить исходный экземпляр.

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)

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

1 Ответ

1 голос
/ 30 марта 2020

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

Но ваша функция 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)
...