web-dev-qa-db-ja.com

UnsafeMutableRawPointerからバイトを取得する方法は?

UnsafeMutableRawPointer(Swift 3で新しく追加された))が指すメモリからバイト(またはInt16、floatなど)にアクセスして、Swift C APIによる機能(コアオーディオなど)

23
hotpaw2

_load<T>_はメモリから生バイトを読み取り、タイプTの値を構築します。

_let ptr = ... // Unsafe[Mutable]RawPointer
let i16 = ptr.load(as: UInt16.self)
_

オプションでバイトオフセットで:

_let i16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
_

assumingMemoryBound()もあり、_Unsafe[Mutable]RawPointer_から_Unsafe[Mutable]Pointer<T>_に変換します。これは、ポイント先のメモリにT型の値が含まれていることを前提としています。

_let i16 = ptr.assumingMemoryBound(to: UInt16.self).pointee
_

値の配列の場合、「バッファポインタ」を作成できます。

_let i16bufptr = UnsafeBufferPointer(start: ptr.assumingMemoryBound(to: UInt16.self), count: count)
_

バッファポインタは既に目的に十分である可能性があります。これは添字付け可能で、配列と同様に列挙できます。必要に応じて、バッファーポインターから配列を作成します。

_let i16array = Array(i16bufptr)
_

@Hamishが言ったように、より多くの情報と詳細はで見つけることができます

43
Martin R

データオブジェクトを作成します。

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

ここでの他の回答から欠落している1つの重要な方法は、UnsafeMutableRawPointerを使用してDataオブジェクトを初期化することです。その後、データオブジェクトを他の計算に使用できます。

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
}
3

Unsafe [Mutable] RawPointerからT/Unsafe [MutablePointer]への変換のAPIドキュメントは次のとおりです。

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

そして、Unsafe[MutablePointer]<T> to Tは、pointeeおよびmove apiを使用して変換できます。

/// 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
1
Ankit Thakur

Swift 4リテラルUInt8配列をUnsafeMutableRawPointerに変換し、UInt32配列に戻す4つの例

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)
}
1
Mike Lee