Sirop4ik
Sirop4ik

Reputation: 5233

How to get UnsafeRawPointer on the swift object?

My app uses the native C++ lib, there is a method that takes as an argument void*

void foo(void * obj) { ... }

in swift I can call this method like this

func boo(obj: MyCustomObj) {
    foo(&obj)
}

and looks like really I get a void pointer on the object, but if I try to get an UnsafeRawPointer on the object like this

func boo(obj: MyCustomObj) {
    var pointer = &obj           <----  Use of extraneous '&'
    foo(pointer)
}

I got an error

Use of extraneous '&'

What is the problem here?

EDIT

I understood that using withUnsafe*** I can get the pointer to the data, but what to do if my method has 2 params, would it looks like this

    withUnsafePointer(to: myObjFirst) {
      pFirst in
      withUnsafePointer(to: myObjSecond) {
        pSecond in
        foo(pFirst, pSecond)
      }
    }

Upvotes: 3

Views: 2392

Answers (1)

Rob Napier
Rob Napier

Reputation: 299275

The & syntax does not mean "the address of" or "pointer to" like in C. In Swift, it is an in-out expression.

These can be used to create implicit pointer conversions as a convenience, and that can seem like C's "pointer to" meaning, but it has very different rules and behaviors. For example, there is no promise that obj even has an address. It may be a tagged pointer. Passing it via an in-out expression may allocate memory and copy the value to make the call possible. Similarly, when passing a "pointer to an array," Swift will actually pass a pointer to a contiguous block of values (which may have been copied to make them contiguous) which is not the same as the actual Array struct.

It is not meaningful to say var pointer = &obj. There is no in-out reference there.

There is no general way to take long-lived pointers to objects in Swift without allocating your own memory (and this is rare). The memory model doesn't promise the kinds of lifetimes you'd need to make that sensible. If your code did compile the way you expect it to, the call to foo(pointer) would still be invalid because there's no promise that obj exists at that point and the pointer could be dangling. (There are no references to obj after the first line, so Swift can and often will destroy it, even though it's still "in scope.")

The foo(&obj) syntax is basically a shorthand for:

withUnsafePointer(to: obj) { foo($0) }

It exists to make it easier to call C functions, but it doesn't mean that Swift pointers are anything like C pointers.

For much more on Swift pointers, see Safely manage pointers in Swift from WWDC 2020.

Upvotes: 3

Related Questions