2016-09-24 53 views
9

根據Swift 3中的Data的文檔,我可以使用一個初始化程序來創建一個來自UnsafeRawPointer的數據。我實際需要的是相反的。我有一個數據,我想創建一個指向數據字節的UnsafeRawPointer。以下是我現在正在做的事情:在Swift 3中,如何從Data獲取UnsafeRawPointer?

1. let data = <from some where> 
2. let unsafePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count) 
3. unsafePointer.initialize(to: 0, count: data.count) // is this necessary? 
4. data.copyBytes(to: unsafePointer, count: data.count) 
5. let unsafeRawPointer = unsafePointer.deinitialize() // this is of the type UnsafeMutalbleRawPointer, and I can use it where UnsafeRawPointer is needed. 

我驗證了這段代碼在Xcode Playground中有效。該代碼甚至可以在沒有行號3的情況下工作。我不確定有或沒有行有什麼區別。無論如何,我的問題是,我是否正確地做我想要的?有沒有更簡單的方法來做到這一點?

回答

16

withUnsafeBytes()給你(鍵入)指針的字節數,這個 可以轉換爲原始指針:

let data = <Data from somewhere> 
data.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in 
    let rawPtr = UnsafeRawPointer(u8Ptr) 
    // ... use `rawPtr` ... 
} 

指針是僅在調用 封閉件的壽命期間有效。

或者,您可以縮小到NSData並訪問原始字節:

let nsData = data as NSData 
let rawPtr = nsData.bytes 

現在指針在同一範圍內,其中nsData有效有效。

+0

解決方案看起來比我的更好,更清潔。第二個也很直接。 – Jake

+0

看來'withUnsafeBytes'對我來說是合適的。它看起來比NSData解決方案更安全 – Jake

+0

'withUnsafeBytes'似乎有限。如果我想要幾個指針來執行所有操作,該怎麼辦? – ryantxr

4

檢查the latest reference

我們找不到從Data獲取UnsafeRawPointer的方法或屬性。

因此,對於選擇: func withUnsafeBytes((UnsafePointer) -> ResultType)

你可以寫這樣的事情:

let data: Data = <initialize it as you like> 

data.withUnsafeBytes {(uint8Ptr: UnsafePointer<UInt8>) in 
    let rawPtr = UnsafeRawPointer(uint8Ptr) 
    //`rawPtr` (and `uint8Ptr`) is guaranteed to be valid in this closure 
    //... 
    //You have no need manage `rawPtr`. 
} 

(呵呵,這是一樣的馬丁的r答案的前半部分。)


但是,如果您想保持UnsafeRawPointer的有效期長於封閉期,則需要製作副本在Data的NT:

例如:

let uint8Ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count) 
uint8Ptr.initialize(from: data) //<-copying the data 
//You need to keep `uint8Ptr` and `data.count` for future management 
let uint8PtrCount = data.count 
//You can convert it to `UnsafeRawPointer` 
let rawPtr = UnsafeRawPointer(uint8Ptr) 
//Use `rawPtr` while `uint8Ptr` is valid 
//... 
//Deinitialize and deallocate the region 
uint8Ptr.deinitialize(count: uint8PtrCount) 
uint8Ptr.deallocate(capacity: uint8PtrCount) 

(你可以得到UnsafeMutableRawPointer作爲deinitialize(count:)返回值,但該區域處於未初始化狀態,所以你不應該訪問的區域。 )

+0

感謝您的兩種解決方案。他們兩人看起來都比我的好。 – Jake

相關問題