简体   繁体   中英

How do I work with a UnsafeMutablePointer<UnsafeMutablePointer<Void>> reference from Swift?

I'm building a test app using the SceneKit's SCNParticleSystem . It has a callback which lets you modify the particles' properties on each frame. The signature of this callback is

typealias SCNParticleModifierBlock = (UnsafeMutablePointer<UnsafeMutablePointer<Void>>, UnsafeMutablePointer<Int>, Int, Int, Float) -> Void

Reference from apple developer site - SCNParticleSystem_Class

I don't know how to access and modify this reference from Swift. If this was C it would be a ** that I could dereference like an array.

After some futzing I've gotten as far as this:

..... 
           particleSystem?.addModifierForProperties([SCNParticlePropertySize], atStage: SCNParticleModifierStage.PostDynamics, withBlock: doit2)
}

struct Foos {
    var size:float_t
}
func doit2(data:UnsafeMutablePointer<UnsafeMutablePointer<Void>>, dataStride: UnsafeMutablePointer<Int>, start:Int, end:Int, deltaTime:Float) -> Void {
    let myptr = UnsafeMutablePointer<UnsafeMutablePointer<Foos>>(data)
    print("indexes",start,end)
    for i in 0 ..< end {
        print(i,myptr[i].memory.size)
    }
}¸

This works for the first particle but crashes on the second. The first time the function is called there are 0 particles, so it skips the loop. The second time there are three particles, so it tries to print them out. The first size value is 0.9 which seams reasonable. The second size value is clearly bogus, and then it crashes and I drop into the debugger.

indexes 0 0
indexes 0 3
0 0.929816
1 1.51296e-39
(lldb)

As near as I can tell no one on the internet uses this function. The only references I find are Apple's docs which provide only ObjC examples for it, not Swift.

Help me!

for examle:

var data = [[0.1, 0.2],[0.3, 0.4],[0.5, 0.6]]
let pData = UnsafeMutablePointer<UnsafeMutablePointer<Void>>(data)
// how to reconstruct the original data ??

// we need to know how much data we have
let count = data.count
// we need to know what type of data we have
let p2 = UnsafeMutablePointer<Array<Double>>(pData)
// access the data
for i in 0..<count {
    print((p2 + i).memory)
}
// [0.1, 0.2]
// [0.3, 0.4]
// [0.5, 0.6]

i think that in your code, the declaration of myptr is wrong

let myptr = UnsafeMutablePointer<UnsafeMutablePointer<Foos>>(data)

dataStride.count in your example should be 1 (number of properties) and value of its element should be size of float (size of the property).

also be careful! your loop should be something like

for i in start..<end {
...
}

are you sure the start is 0 ???

Working with the very similar SCNParticleEventBlock, I wrote the handler in Swift3 as

 ps.handle(SCNParticleEvent.birth, forProperties [SCNParticleSystem.ParticleProperty.color]) {
    (data:UnsafeMutablePointer<UnsafeMutableRawPointer>, dataStride:UnsafeMutablePointer<Int>, indicies:UnsafeMutablePointer<UInt32>?, count:Int) in

    for i in 0..<count {

        // get an UnsafeMutableRawPointer to the i-th rgba element in the data
        let colorsPointer:UnsafeMutableRawPointer = data[0] + dataStride[0] * i

        //  convert the UnsafeMutableRawPointer to a typed pointer by binding it to a type:
        let floatPtr = colorsPointer.bindMemory(to: Float.self, capacity: dataStride[0])
        // convert that to a an  UnsafeMutableBufferPointer
        var rgbaBuffer = UnsafeMutableBufferPointer(start: floatPtr, count: dataStride[0])
        // At this point, I could convert the buffer to an Array, but doing so copies the data into the array and any changes made in the array are not reflected in the original data.  UnsafeMutableBufferPointer are subscriptable, nice.
        //var rgbaArray = Array(rgbaBuffer)

        // about half the time, mess with the red and green components
        if(arc4random_uniform(2) == 1) {
            rgbaBuffer[0] = rgbaBuffer[1]
            rgbaBuffer[1] = 0
        }
    }
 }

A little more detail in my SO asked and answered question here

And a couple gists here and here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM