Cast to Different C Struct Unsafe Pointer in Swift

Cast to different C struct unsafe pointer in Swift

You can write something like this:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1) {sockaddrPtr in
bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
}
}

Or someone suggests this may be better:

withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
let sockaddrPtr = UnsafeRawPointer(sockaddrInPtr).assumingMemoryBound(to: sockaddr.self)
bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
}

This article may be some help.


(UPDATE)
As described in the link shown by Martin R, now MemoryLayout<T>.stride and MemoryLayout<T>.size return the same value which is consistent with C's sizeof, where T is an imported C-struct. I'll keep my stride version of answer here, but that is not something "required" in this case now.

Cast C struct double pointer to a Swift struct unsafe pointer

Let's think about that in terms of what's happening in C. When I do a cast of pointers in C, the data that represents the pointer type will now be treated as a pointer of a different type. The value of the pointer doesn't change, just how you treat it.

Swift doesn't like to do this kind of thing and doesn't encourage you to do it because while cheap, it's a fundamentally unsafe thing to do and can lead to corrupting data, jumping into space, bus errors, etc.

That doesn't mean that swift doesn't have the ability to do this. The link that you point to uses withUnsafePointerTo which tries to limit the scope of the use of the pointer. In your case, you probably want to look at unsafeBitCast (documentation here) which mimics the C pointer cast (it's not strictly the same as C casting in general, but for pointers it is).

let a:UnsafeMutablePointer<SomeType> = fetchASomeTypePointer()
let b = unsafeBitCast(a, to: UnsafeMutablePointer<SomeOtherType>.self)

This makes the data representing the pointer to SomeType now become a pointer to SomeOtherType.

Like I said before, this is a dangerous thing to do especially if you don't fully understand what you're doing.

Cast a Swift struct to UnsafeMutablePointer Void

As far as I know, the shortest way is:

var myStruct = TheStruct()
var address = withUnsafeMutablePointer(&myStruct) {UnsafeMutablePointer<Void>($0)}

But, why you need this? If you want pass it as a parameter, you can (and should):

func foo(arg:UnsafeMutablePointer<Void>) {
//...
}

var myStruct = TheStruct()
foo(&myStruct)

Swift casting unsafemutablepointer MyStruct to C void return pointer in swift

look at this 'self explanatory' example

struct MyStruct {
var myId: Int
var myDouble: Double
}

var myStruct = MyStruct(myId: 1, myDouble: 1.0)

// this mimics the funcion which returns Void *myStruct
var vptr = withUnsafeMutablePointer(&myStruct) { (pStruct) -> UnsafeMutablePointer<Void> in
return UnsafeMutablePointer<Void>(pStruct)
}
print(vptr) // 0x00000001079c7828
// mimics mPtr = (MyStruct *) vptr
let mPtr = UnsafeMutablePointer<MyStruct>(vptr) // UnsafeMutablePointer(0x10EE37838)

mPtr.memory.myId = 10
mPtr.memory.myDouble = 10.0

print(myStruct) // MyStruct(myId: 10, myDouble: 10.0)

Casting between different UnsafePointer T in swift

struct UnsafePointer<T> has a constructor

/// Convert from a UnsafePointer of a different type.
///
/// This is a fundamentally unsafe conversion.
init<U>(_ from: UnsafePointer<U>)

which you can use here

doThingsOnRawData(UnsafePointer<UInt8>(data.bytes))

You can even omit the generic type because it is inferred from the context:

doThingsOnRawData(UnsafePointer(data.bytes))

Update for Swift 3: As of Xcode 8 beta 6, you cannot convert
directly between different unsafe pointers anymore.

For data: NSData, data.bytes is a UnsafeRawPointer which can
be converted to UnsafePointer<UInt8> with assumingMemoryBound:

doThingsOnRawData(data.bytes.assumingMemoryBound(to: UInt8.self))

For data: Data it is even simpler:

data.withUnsafeBytes { doThingsOnRawData($0) }

Cast UnsafeMutablePointer Void to my struct type

Just a guess referencing from here

struct YourStruct {
var name : String
}
var structInstance = YourStruct.init(name: "Jose")

func delegateMethod(voidPtr : UnsafePointer<Void>) {
//CONVERSION HERE
let myStruct = UnsafePointer<YourStruct>(voidPtr).memory
print("\(myStruct.name)")
}
delegateMethod(&structInstance)

casting address of swift struct to C pointer of specific type

If you declare the struct as a variable

var someData = SomeStruct(someValue: 1)

then you can use withUnsafe(Mutable)Pointer() to get a pointer:

withUnsafeMutablePointer(&someData) {
myFunc(UnsafeMutablePointer($0), UInt8(sizeof(SomeStruct)))
}

This guarantees that the pointer is only used while the structure is
valid.

If the C function takes a constant pointer

 myFunc(const u8* data, u8 lengthOfData);

then you don't need mutable pointers:

withUnsafePointer(&someData) {
myFunc(UnsafePointer($0), UInt8(sizeof(SomeStruct)))
}

But note that the layout of Swift structures is not defined and may
change. For data structures needed in both Swift and C it may be
safer to define them as C structures in the C header files instead.

How to cast self to UnsafeMutablePointer Void type in swift

An object pointer (i.e. an instance of a reference type) can be
converted to a UnsafePointer<Void> (the Swift mapping of const void *, UnsafeRawPointer in Swift 3) and back. In Objective-C you would write

void *voidPtr = (__bridge void*)self;
//
MyType *mySelf = (__bridge MyType *)voidPtr;

(See 3.2.4 Bridged casts in the Clang ARC documentation for the precise meaning of these
casts.)

Swift has an Unmanaged type for that purpose.
It is a bit cumbersome to use because it works with COpaquePointer
instead of UnsafePointer<Void>. Here are two helper methods
(named after the Objective-C __bridge cast):

func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
}

func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
}

The "complicated" expression is only necessary to satisfy Swifts
strict type system. In the compiled code this is just a cast
between pointers. (It can be written shorter as indicated in the *** comments
if you are willing to use "unsafe" methods, but the compiled
code is identical.)

Using this helper methods you can pass self to a C function as

 let voidPtr = bridge(self)

(or UnsafeMutablePointer<Void>(bridge(self)) if the C function requires
a mutable pointer), and convert it back to an object pointer – e.g.
in a callback function – as

 let mySelf : MyType = bridge(voidPtr)

No transfer of ownership takes place, so you must ensure that self
exists as long as the void pointer is used.


And for the sake of completeness, the Swift equivalent of __bridge_retained and __bridge_transfer from Objective-C would be

func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passRetained(obj).toOpaque())
}

func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeRetainedValue()
}

bridgeRetained() casts the object pointer to a void pointer and
retains the object. bridgeTransfer() converts the
void pointer back to an object pointer and consumes the retain.

An advantage is that the object cannot be deallocated between the
calls because a strong reference is held. The disadvantage is that
the calls must be properly balanced, and that it can easily cause retain
cycles.


Update for Swift 3 (Xcode 8):

func bridge<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}

func bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}

func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())
}

func bridgeTransfer<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}

The relevant changes to "unsafe pointers" are described in

  • SE-0017 Change Unmanaged to use UnsafePointer
  • SE-0107 UnsafeRawPointer API

C-style pointer/array casting in Swift?

Let’s assume the byteArray had eight bytes in it. You could do:

let byteArray: [UInt8] = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7]

let value = byteArray.withUnsafeBytes {
$0.bindMemory(to: UInt64.self)[0].littleEndian // or .bigEndian
}

Resulting in:

0x0706050403020100     // or 0x0001020304050607 if you use bigEndian

Or, if you had enough bytes for multiple UInt64, you could do:

let longByteArray: [UInt8] = [
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf
]

let values = longByteArray.withUnsafeBytes {
$0.bindMemory(to: UInt64.self)
}.map {
$0.littleEndian // or .bigEndian
}

Resulting in

[0x0706050403020100, 0x0f0e0d0c0b0a0908] // or [0x0001020304050607, 0x08090a0b0c0d0e0f] if you use bigEndian


Related Topics



Leave a reply



Submit