什么是 UnsafeMutablePointer<Void>?如何修改底层内存?

Posted

技术标签:

【中文标题】什么是 UnsafeMutablePointer<Void>?如何修改底层内存?【英文标题】:What is UnsafeMutablePointer<Void>? How to modify the underlying memory? 【发布时间】:2015-02-08 19:57:58 【问题描述】:

我正在尝试使用 SpriteKit 的 SKMutableTexture 类,但我不知道如何使用 UnsafeMutablePointer&lt; Void &gt;。我有一个模糊的想法,它是指向内存中连续字节数据的指针。但是我该如何更新呢?这在代码中实际上会是什么样子?

编辑

这是一个基本的代码示例。我怎样才能让它做一些简单的事情,比如在屏幕上创建一个红色方块?

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

        /* ??? */

    

【问题讨论】:

【参考方案1】:

来自SKMutableTexture.modifyPixelDataWithBlock 的文档:

假定纹理字节存储为紧密压缩的 32 bpp、8bpc(无符号整数)RGBA 像素数据。您提供的颜色分量应该已经乘以 alpha 值。

因此,当您获得 void* 时,基础数据是 4x8 位流的形式。

你可以像这样操作这样的结构:

// 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
    

【讨论】:

刚刚在 Xcode 中使用示例 SpriteKit 项目进行了尝试,似乎做了正确的事情——但我对 SpriteKit一无所知,所以不能保证这是“方法”去做。 谢谢你这工作。我现在在屏幕上看到一个正方形,但是,我希望每帧调用一次 modifyPixelDataWithBlock 方法——就像片段着色器的某种替代方法一样,但该块只被调用一次。更多挖掘... 请注意,您需要传入预乘以 RGB 部分的 alpha 值。来自docsThe 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.【参考方案2】:

UnsafeMutablePointer&lt;Void&gt;void* 的 Swift 等价物——一个指向任何东西的指针。您可以访问底层内存作为其memory 属性。通常,如果您知道底层类型是什么,您将首先强制指向该类型的指针。然后,您可以使用下标到达内存中的特定“槽”。

例如,如果数据确实是 UInt8 值的序列,你可以说:

let buffer = UnsafeMutablePointer<UInt8>(ptr)

您现在可以以buffer[0]buffer[1] 等形式访问各个 UIInt8 值。

【讨论】:

更多信息请参见我的 Swift 教程:apeth.com/swiftBook/apa.html#_c_pointers 从modifyPixelDataWithBlock的方法签名来看,我认为底层类型是8位整数。演员在代码中的实际样子是什么?我真的希望有一些关于如何做到这一点的代码示例 如果它是一个 8 位整数,那将是一个 Int8 或 UInt8。因此,如果您转换为 UnsafeMutablePointer 或 UnsafeMutablePointer,无论它是什么,您都可以使用下标按数字获取单个字节。 我会将什么转换为 UnsafeMutablePointer?您能提供一个简单的代码示例作为起点吗?请参阅我对原始问题的编辑。谢谢! 是的,抱歉,当我说“演员”时,我应该说“强制”。

以上是关于什么是 UnsafeMutablePointer<Void>?如何修改底层内存?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理 UnsafeMutablePointer

iOS:将 UnsafeMutablePointer<Int8> 快速转换为字符串?

如何在 Swift 中使用 UnsafeMutablePointer<OpaquePointer>?

参数对于 UnsafeMutablePointer<Type>.alloc() 有啥意义?

Swift UnsafeMutablePointer:我必须在释放之前调用 deinitialize 吗?

如何将 UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> 转换为 UnsafeMutablePointer<Unsafe