2016-08-16 33 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) 
}