Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is UnsafeMutablePointer<Void>? How to modify the underlying memory?

I am trying to work with SpriteKit's SKMutableTexture class but I don't know how to work with UnsafeMutablePointer< Void >. I have a vague idea that it is a pointer to a succession of byte data in memory. But how can I update it? What would this actually look like in code?

Edit

Here is a basic code sample to work with. How would I get this to do something as simple as create a red square on the screen?

    let tex = SKMutableTexture(size: CGSize(width: 10, height: 10))
    tex.modifyPixelDataWithBlock { (ptr:UnsafeMutablePointer<Void>, n:UInt) -> Void in

        /* ??? */

    }
like image 558
Bret Avatar asked Feb 08 '15 19:02

Bret


People also ask

What is an UnsafeMutablePointer?

UnsafeMutablePointer provides no automated memory management or alignment guarantees. You are responsible for handling the life cycle of any memory you work with through unsafe pointers to avoid leaks or undefined behavior. Memory that you manually manage can be either untyped or bound to a specific type.

Do we have pointers in Swift?

Swift's typed pointers give you direct access to memory, but only within the confines of type safety. You can't have two typed pointers to the same memory that disagree on the type. So, if your goal is to reinterpret bytes of memory as different types, then you need use a lower-level API.

How do you define a pointer in Swift?

A pointer is an object that stores a memory address. In Swift, there are 8 types of pointers. In Swift, pointers are known as UnsafePointer because they support direct operations on memory and these operations are unsafe in nature that's why a Unsafe prefix is used with Pointers in swift.


1 Answers

From the docs for SKMutableTexture.modifyPixelDataWithBlock:

The texture bytes are assumed to be stored as tightly packed 32 bpp, 8bpc (unsigned integer) RGBA pixel data. The color components you provide should have already been multiplied by the alpha value.

So, while you’re given a void*, the underlying data is in the form of a stream of 4x8 bits.

You could manipulate such a structure like so:

// struct of 4 bytes
struct RGBA {
    var r: UInt8
    var g: UInt8
    var b: UInt8
    var a: UInt8
}

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10))
tex.modifyPixelDataWithBlock { voidptr, len in
    // convert the void pointer into a pointer to your struct
    let rgbaptr = UnsafeMutablePointer<RGBA>(voidptr)

    // next, create a collection-like structure from that pointer
    // (this second part isn’t necessary but can be nicer to work with)
    // note the length you supply to create the buffer is the number of 
    // RGBA structs, so you need to convert the supplied length accordingly...
    let pixels = UnsafeMutableBufferPointer(start: rgbaptr, count: Int(len / sizeof(RGBA))

    // now, you can manipulate the pixels buffer like any other mutable collection type
    for i in indices(pixels) {
        pixels[i].r = 0x00
        pixels[i].g = 0xff
        pixels[i].b = 0x00
        pixels[i].a = 0x20
    }
}
like image 200
Airspeed Velocity Avatar answered Oct 10 '22 09:10

Airspeed Velocity