How to get bytes out of an UnsafeMutableRawPointer?

后端 未结 4 1061
孤独总比滥情好
孤独总比滥情好 2020-12-02 21:05

How does one access bytes (or Int16\'s, floats, etc.) out of memory pointed to by an UnsafeMutableRawPointer (new in Swift 3) handed to a Swift function by a C API (Core Aud

相关标签:
4条回答
  • 2020-12-02 21:24

    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
    0 讨论(0)
  • 2020-12-02 21:30

    Create Data object.

    init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Data.Deallocator)
    

    One important way missing from the other answers here is initialising a Data object with UnsafeMutableRawPointer. The data object can then be used for other calculations.

    public func base64(quality: Int32 = 67) -> String? {
        var size: Int32 = 0
        if let image = gdImageJpegPtr(internalImage, &size, quality) {
            // gdImageJpegPtr returns an UnsafeMutableRawPointer that is converted to a Data object
            let d = Data(bytesNoCopy: image, count: Int(size), deallocator: .none)
            return d.base64EncodedString()
        }
        return nil
    }
    
    0 讨论(0)
  • 2020-12-02 21:31

    Here's a Swift 4 example of converting a literal UInt8 array to an UnsafeMutableRawPointer and back to an UInt32 array

    static func unsafePointerTest() {
        //let a : [UInt8] = [0,0,0,4,0,0,0,8,0,0,0,12]
        let a : [UInt8] = [0x04, 0x00, 0x00, 0x00,
                           0x08, 0x00, 0x00, 0x00,
                           0x0C, 0x00, 0x00, 0x00] //little endian
        //0xFF, 0xF0, 0xF0, 0x12]  //317780223 = 12F0F0FF
        let b:UnsafeMutableRawPointer = UnsafeMutableRawPointer(mutating:a)
        let bTypedPtr = b.bindMemory(to: UInt32.self, capacity: a.count/4)
        let UInt32Buffer = UnsafeBufferPointer(start: bTypedPtr, count: a.count/4)
        let output = Array(UInt32Buffer)
        print(output)
    }
    
    0 讨论(0)
  • 2020-12-02 21:39

    Here are the api documentation of Unsafe[Mutable]RawPointer to T/Unsafe[MutablePointer] conversion:

    /// Binds the allocated memory to type `T` and returns an
    /// `UnsafePointer<T>` to the bound memory at `self`.
    ///
    /// - Precondition: The memory is uninitialized.
    /// - Postcondition: The memory is bound to 'T' starting at `self` continuing
    ///   through `self` + `count` * `MemoryLayout<T>.stride`
    /// - Warning: Binding memory to a type is potentially undefined if the
    ///   memory is ever accessed as an unrelated type.
    public func bindMemory<T>(to type: T.Type, capacity count: Int) -> UnsafePointer<T>
    
    /// Converts from an `UnsafeRawPointer` to UnsafePointer<T> given that
    /// the region of memory starting at `self` is already bound to type `T`.
    ///
    /// - Precondition: The memory is bound to 'T' starting at `self` for some
    ///   unspecified capacity.
    ///
    /// - Warning: Accessing memory via the returned pointer is undefined if the
    ///   if the memory has not been bound to `T`.
    public func assumingMemoryBound<T>(to: T.Type) -> UnsafePointer<T>
    
    /// Reads raw bytes from memory at `self + offset` and constructs a
    /// value of type `T`.
    ///
    /// - Precondition: The underlying pointer plus `offset` is properly
    ///   aligned for accessing `T`.
    ///
    /// - Precondition: The memory is initialized to a value of some type, `U`,
    ///   such that `T` is layout compatible with `U`.
    public func load<T>(fromByteOffset offset: Int = default, as type: T.Type) -> T
    

    and then from Unsafe[MutablePointer]<T> toT can be converted with pointee and move apis

    /// Accesses the `Pointee` instance referenced by `self`.
    ///
    /// - Precondition: the pointee has been initialized with an instance of
    ///   type `Pointee`.
    public var pointee: Pointee { get }
    
    /// Retrieves the `pointee`, returning the referenced memory to an
    /// uninitialized state.
    ///
    /// Equivalent to `{ defer { deinitialize() }; return pointee }()`, but
    /// more efficient.
    ///
    /// - Precondition: The pointee is initialized.
    ///
    /// - Postcondition: The memory is uninitialized.
    public func move() -> Pointee
    
    0 讨论(0)
提交回复
热议问题