2016-08-16 37 views
18

如何訪問由UnsafeMutableRawPointer(Swift 3中新增)所指向的內存中的字節(或Int16的,浮點等)由C API交付Swift函數(Core Audio等)如何從UnsafeMutableRawPointer中獲取字節?

+1

能否請您給我們一個[最小的,完整的和可驗證的示例](HTTP ://stackoverflow.com/help/mcve)的一些具體的數據工作? – Alexander

+2

[不安全路由指針的Swift進化提議](https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md)可能是一個很好的開始 - 提供一個很好的概述用API舉例說明。 – Hamish

回答

34

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()其中從01轉換到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所述,更多的信息和細節可以在

+0

謝謝!這適用於第一個元素。對於UInt16的(複數)如何,因爲可能有一組數據? (例如,在Int16音頻採樣緩衝區中) – hotpaw2

+2

@ hotpaw2:請參閱更新。 –

+0

ptr。assumeMemoryBound(to:Int16.self).pointee = Int16(foo()); ptr + = 2 //似乎也適用於按順序分配數組元素 – hotpaw2

1

下面是api文檔不安全[Mutable] RawPointer to T/Unsafe [MutablePointer]轉換:

/// 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>T可以與 pointeemove的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 
3

創建數據對象。從其他的答案在這裏失蹤

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

一個重要方式是與初始化一個UnsafeMutableRawPointer數據對象。數據對象可以用於其他計算。

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

這來得非常方便!我需要將dealloc更改爲none,但這對我來說是個訣竅。非常感謝。 – VaporwareWolf

1

這裏的文字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) 
}