Pointers, Pointer Arithmetic, and Raw Data in Swift

Pointers, Pointer Arithmetic, and Raw Data in Swift

If you just want to do it directly, UnsafePointer<T> can be manipulated arithmetically:

   let oldPointer = UnsafePointer<()>
let newPointer = oldPointer + 10

You can also cast a pointer like so (UnsafePointer<()> is equivalent to void *)

   let castPointer = UnsafePointer<MyStruct>(oldPointer)

How to do pointer arithmetic on UnsafeMutablePointer and get String in Swift 3

You have to bind the raw pointer to an UInt8 pointer:

let bytes = (data + 1).bindMemory(to: UInt8.self, capacity: length - 1)

Now you can create a buffer pointer referring to that byte range

let buffer = UnsafeBufferPointer(start: bytes, count: length - 1)

which (as a Sequence) can be passed to

let str = String(bytes: buffer, encoding: .ascii)

Pointers in swift: purpose of UnsafeMutableBufferPointer

UnsafeMutablePointer<T> is designed for accessing a single element of type T. Its interface is designed for accessing a single scalar value.

UnsafeMutableBufferPointer<T>, on the other hand, is designed to access a group of elements of type T stored in a contiguous block of memory. Its interface is designed to access individual elements of the range, and also for treating the entire collection as a single unit (e.g. the generate method).

If you access bytes inside NSData, UnsafePointer alone is not sufficient, because you need to know the length of data. In contrast, a single UnsafeBufferPointer is sufficient to represent the data, because it provides both the initial location and the number of elements.

Pointer and malloc in Swift

You can use malloc from Swift, it returns a "raw pointer":

var p: [UnsafeMutableRawPointer?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0

p[allocatedMB] = malloc(1048576)
memset(p[allocatedMB], 0, 1048576)

Alternatively, use UnsafeMutablePointer and its
allocate and initialize methods:

var p: [UnsafeMutablePointer<UInt8>?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0

p[allocatedMB] = UnsafeMutablePointer.allocate(capacity: 1048576)
p[allocatedMB]?.initialize(to: 0, count: 1048576)

Swift, OpenGL and glVertexAttribPointer

To replicate the offsetof functionality you just need to know at which byte offset does each field lie in your structure.

In your case, assuming your struct is tightly packed, the first call should receive 0, and the second 4 * GLfloat because that's the size of the first component. I'm not sure how to extract this data directly from the structure, especially since you're using tuples.

To illustrate, your structure:

struct Vertex {
var position: (x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)
var color: (r: GLfloat, g: GLfloat, b: GLfloat, a: GLfloat)
}

is most probably laid out like that:

GLfloat // <-- structure start // <-- position
GLfloat
GLfloat
GLfloat
GLfloat // <-- color
GLfloat
GLfloat
GLfloat

Hence the position lies at offset 0, and color at 4 * GLfloat.


To create a pointer with a value 16, this answer looks relevant:

let ptr = UnsafePointer<()> + 16

So I suppose this should work as well:

let ptr = UnsafePointer<()> + sizeof(GLfloat) * 4

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

Passing swift struct pointer to C function

There are two problems: You cannot take the address of a constant (defined with let),
and you can pass the address of a variable only to function parameters.
Assuming that your C function is

void myFunc(const void *data);

then this would work:

var a = Foo()
myFunc(&a)

However, instead of making assumptions about identical alignment in C and Swift, you
should perhaps better define the structure in your C API:

struct Foo {
float a;
float b;
float c;
double d;
};

void myFunc(const struct Foo *data);

and use that from the Swift code:

var a = Foo(a: 0, b: 0, c: 0, d: 0)
myFunc(&a)

Convert UnsafeMutableRawPointer to UInt64

(U)Int has the size of a pointer on all platforms (32 bit or 64 bit), so you can always convert between Unsafe(Mutable)(Raw)Pointer and Int or UInt:

let pointer: UnsafeRawPointer? = ...
let intRepresentation = UInt(bitPattern: pointer)
let ptrRepresentation = UnsafeRawPointer(bitPattern: intRepresentation)
assert(ptrRepresentation == pointer)

Your code

let intRepresentation = UInt64(bitPattern: pointer) 

does not compile because UInt64 does not have an initializer taking a pointer argument, and that is because pointers can be 32 bit or 64 bit. (And even on a 64-bit platform, UInt and UInt64 are distinct types.)

If you need an UInt64 then

let intRepresentation = UInt64(bitPattern:Int64(Int(bitPattern: pointer)))

does the trick.



Related Topics



Leave a reply



Submit