Unsaferawpointer Assumingmemorybound VS. Bindmemory

UnsafeRawPointer assumingMemoryBound vs. bindMemory

Allocated memory in Swift can either be:

  • Uninitialised raw memory
  • Uninitialised memory that's bound to a type
  • Initialised memory bound to a type

When you allocate memory with UnsafeMutableRawPointer.allocate(bytes:alignedTo:), you get uninitialised raw memory.

When you allocate memory with UnsafeMutablePointer<T>.allocate(capacity:), you get uninitialised memory that's bound to the type T.

  • bindMemory(to:capacity:) (re-)binds a pointer's memory to a new type, and gives you back a typed pointer to access it with. It can be called on a pointer to memory in any of the above states; though if the memory is initialised, the new bound type must be layout compatible with the old bound type, and both types should be trivial.

    Note that this method doesn't perform allocation or initialisation; it merely changes the bound type of the memory.

  • assumingMemoryBound(to:) is a method for getting a typed pointer from a raw pointer that you already know points to memory bound to a given type. If the memory is not bound to this type, accessing memory through the typed pointer you get back is undefined behaviour.

One important thing to note here is that memory can only be bound to one type at a given time. You are free to rebind to other types (with the above restriction for initialised memory); however attempting to access memory bound to a given type as an unrelated type violates strict aliasing and is therefore undefined behaviour.

Another thing to note is that related types and layout compatible types are independent concepts:

  • The type T is layout compatible with the type U if memory bound to type U can be bitwise reinterpreted as having type T. Note that this isn't necessarily a bidirectional relationship. For example, Int is layout compatible with (Int, Int) if one 'instance' of (Int, Int) can be reinterpreted as being 2 x Int. The reverse can't be true though; you can't form an (Int, Int) value from a single Int.

  • Two types are related if you can alias overlapping memory with those types. For example, if you have an UnsafePointer<T> and an UnsafePointer<U>, if T and U are unrelated types, then they cannot point to memory that overlaps with each other.

However, I don't believe Swift has officially defined any rules for these terms yet (I expect this'll come with ABI stability).

So what's different after bindMemory(to:capacity:) completes?

Currently, nothing. As Andrew Trick says in the mailing list discussion that Martin linked to:

Binding memory communicates to the compiler that the memory locations are safe for typed access. Nothing happens at runtime--until someone writes a type safety sanitizer. It affects the abstract state of the memory location, independent of the pointer variable used to access that memory. Binding memory returns a typed pointer for convenience and clarity, but there’s nothing special about that particular pointer value.

For further reading on this subject, see the memory model explanation section of SE-0107, as well as this unofficial guide to strict aliasing in Swift.

How to convert Data to UnsafePointer UInt8 ?

The correct way is to use bindMemory():

data.withUnsafeBytes { (unsafeBytes) in
let bytes = unsafeBytes.bindMemory(to: UInt8.self).baseAddress!
do_something(bytes, unsafeBytes.count)
}

assumingMemoryBound() must only be used if the memory is already bound to the specified type.

Some resources about this topic:

  • UnsafeRawPointer Migration Guide
  • UnsafeRawPointer API

How to get bytes out of an UnsafeMutableRawPointer?

load<T> reads raw bytes from memory and constructs a value of type T:

let ptr = ... // Unsafe[Mutable]RawPointer
let i16 = ptr.load(as: UInt16.self)

optionally at a byte offset:

let i16 = ptr.load(fromByteOffset: 4, as: UInt16.self)

There is also assumingMemoryBound() which converts from a Unsafe[Mutable]RawPointer to a Unsafe[Mutable]Pointer<T>, assuming that the pointed-to memory contains a value of type T:

let i16 = ptr.assumingMemoryBound(to: UInt16.self).pointee

For an array of values you can create a "buffer pointer":

let i16bufptr = UnsafeBufferPointer(start: ptr.assumingMemoryBound(to: UInt16.self), count: count)

A buffer pointer might already be sufficient for your purpose, it
is subscriptable and can be enumerated similarly to an array.
If necessary, create an array from the buffer pointer:

let i16array = Array(i16bufptr)

As @Hamish said, more information and details can be found at

  • SE-0107 UnsafeRawPointer API

Cannot invoke initializer for type UnsafePointer _ with an argument list of type (UnsafeMutableRawPointer)

Please check the official reference when some sort of spec changes has affected with your code. In your case AudioBuffer.mData is of type UnsafeMutableRawPointer?, and you need to pass it to the first argument of OutputStream.write(_:maxLength:) of type UnsafePointer<UInt8>.

UnsafeMutableRawPointer

You can find this method which returns UnsafeMutablePointer<T>:

func assumingMemoryBound<T>(to: T.Type)

The concept of bound is sort of confusing, but seems you can use it for pointer type conversion:

outputStreme?.write(buffer.mData!.assumingMemoryBound(to: UInt8.self), maxLength: Int(buffer.mDataByteSize))

(Assuming forced-unwrapping ! is safe enough as suggested by your print(buffer.mData!).)

Memory bound-ness is not well defined for most APIs which return pointers, and has no effect as for now. There's another type conversion method func bindMemory<T>(to: T.Type, capacity: Int), and both work without problems (again, as for now).

MDQueryGetResultAtIndex and UnsafeRawPointer in Swift 3

The problem in your code

if let item = MDQueryGetResultAtIndex(q, 0) {
let ptr = item.bindMemory(to: MDItem.self, capacity: 1)
let path = MDItemCopyAttribute(ptr.pointee, kMDItemPath)
}

is that the UnsafeRawPointer is interpreted as a pointer to an
MDItem reference and then dereferenced in ptr.pointee, but
the raw pointer is the MDItem reference, so it is dereferenced
once too often.

The "shortest" method to convert the raw pointer to an MDItem reference
is unsafeBitCast:

let item = unsafeBitCast(rawPtr, to: MDItem.self)

which is the direct analogue of an (Objective-)C cast.
You can also use the Unmanaged methods
to convert the raw pointer to an unmanaged reference and from there
to a managed reference (compare How to cast self to UnsafeMutablePointer<Void> type in swift):

let item = Unmanaged<MDItem>.fromOpaque(rawPtr).takeUnretainedValue()

This looks a bit more complicated but perhaps expresses the intention
more clearly. The latter approach works also with (+1) retained
references (using takeRetainedValue()).

Self-contained example:

import CoreServices

let queryString = "kMDItemContentType = com.apple.application-bundle"
if let query = MDQueryCreate(kCFAllocatorDefault, queryString as CFString, nil, nil) {
MDQueryExecute(query, CFOptionFlags(kMDQuerySynchronous.rawValue))

for i in 0..<MDQueryGetResultCount(query) {
if let rawPtr = MDQueryGetResultAtIndex(query, i) {
let item = Unmanaged<MDItem>.fromOpaque(rawPtr).takeUnretainedValue()
if let path = MDItemCopyAttribute(item, kMDItemPath) as? String {
print(path)
}
}
}
}

UnsafePointer no longer works in swift 3

You can try this:

let rawPointer = UnsafeRawPointer(array1)
let pointer = rawPointer.assumingMemoryBound(to: UInt32.self)
let value = pointer.pointee

Raw pointer is a pointer for accessing untype data.

assumingMemoryBound(to:) can convert from an UnsafeRawPointer to UnsafePointer<T>.

Reference :Swift 3.0 Unsafe World

Value of type 'UnsafeMutableRawPointer' has no subscripts Swift 5

You need to assign a type to your mutable pointer. In the current state it is a mutable pointer to anything but you want it to be a mutable pointer to a buffer of UInt8 values.

To do so simply call assumingMemoryBound on your data:

let data = calloc(bytesPerRow, height)!.assumingMemoryBound(to: UInt8.self)

Swift 5.0: 'withUnsafeBytes' is deprecated: use `withUnsafeBytes R (...)

In Swift 5 the withUnsafeBytes() method of Data calls the closure with an (untyped) UnsafeRawBufferPointer, and you can load() the value from the raw memory:

let value = data.withUnsafeBytes { $0.load(as: UInt32.self) }

(compare How to use Data.withUnsafeBytes in a well-defined manner? in the Swift forum). Note that this requires that the memory is aligned on a 4-byte boundary. For alternatives see round trip Swift number types to/from Data.

Note also that as of Swift 4.2 you can create a random 32-bit integer simply using the new Random API:

let randomId = UInt32.random(in: .min ... .max)

Pointers in Swift

  1. Is UnsafePointer <T> equal to const T * Pointer in ? and UnsafeMutablePointer <T> is equal to T * Pointer in C?

Well, use a bridging header in a Swift app to see how the C pointers are bridged:

const int *myInt;
int *myOtherInt;

bridges to

var myInt: UnsafePointer<Int32>!
var myOtherInt: UnsafeMutablePointer<Int32>!

  1. What is the difference between Unsafe[Mutable]Pointer and UnsafeRaw[Mutable]Pointer?

Swift 3 added a UnsafeRawPointer API to replace the Unsafe[Mutable]Pointer<Void> type. Conversion between pointers of a different type is no longer allowed in Swift. Instead, the API provides interfaces (.assumingMemoryBound(to:) or .bindMemory(to:capacity:)) to bind memory to a type.

With regard to question 3, the ampersand means that the variable is inout. I don't believe you can declare a variable as inout unless it is being used by a function that directly modifies the underlying memory, but I'll let the experts correct me. Instead, use withUnsafePointer.

Thanks to Martin's helpful comment, this syntax was never valid in Swift, and there is no safe way to create "free pointers" to Swift variables.

Convert UnsafeMutableRawPointer to UnsafeMutablePointer T in swift 3

In your case, you'd better use allocate(capacity:) method.

let grayData = UnsafeMutablePointer<UInt8>.allocate(capacity: width * height)


Related Topics



Leave a reply



Submit