简体   繁体   English

如何转换UnsafePointer &lt;[Float]&gt;或将Float Array数据拟合到Unsafe [Mutable]指针 <Float> 在Swift 3中?

[英]How to convert UnsafePointer<[Float]> or fit Float Array data to Unsafe[Mutable]Pointer<Float> in Swift 3?

I have an array of float value ( floatArray ) coming from HDF5 file, and I'd like to use this data as an input for the function that accepts Unsafe[Mutable]Pointer ( inputForFunction ). 我有一个来自HDF5文件的浮点数值( floatArray ),我想使用这些数据作为接受Unsafe [Mutable]指针( inputForFunction )的函数的输入。 I'm new to UnsafePointer, so I need someone's help. 我是UnsafePointer的新手,所以我需要别人的帮助。

One way I have in mind is, to store the array to a file, then to open it and to map the file descriptor to the memory of the variable for the input of the function: 我想到的一种方法是,将数组存储到文件中,然后打开它并将文件描述符映射到变量的内存中以输入函数:

  // read the data from HDF5 file
  var floatArray: [Float] = try originalHDF5DataSet.read()

  // store the data
  let dataToStore = NSData(bytes: &floatArray, length: sizeOfArray * MemoryLayout<Float>.size)
  let tmpPath = URL(fileURLWithPath: NSTemporaryDirectory())
  let filePath = tmpPath.appendingPathComponent("floatArrayData").appendingPathExtension("dat")
  do{
    try data.write(to: filePath, options: .atomic)
    let fileManager : FileManager   = FileManager.default
    if fileManager.fileExists(atPath:filePath.path){
      print("Success")
    }else{
      print("Fail")
    }

    // open the data 
    let dataPath = filePath.path
    let fd = open(dataPath, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
    assert(fd != -1, "Error: failed to open output file at \""+dataPath+"\"  errno = \(errno)\n")
    // memory map the parameters
    let hdr = mmap(nil, Int(sizeOfArray), PROT_READ, MAP_FILE | MAP_SHARED, fd, 0)
    // cast Void pointers to Float
    let inputForFunction = UnsafePointer<Float>(hdr!.assumingMemoryBound(to: Float.self))
  } catch{
    print("failed")
  }

However, it may not be the best implementation because the process to store the data seems time-consuming. 但是,它可能不是最佳实现,因为存储数据的过程看起来很耗时。

That's why I'm considering to use UnsafePointer to pass the pointer from floatArray to inputForFunction , but I'm not sure how to implement it. 这就是我考虑使用UnsafePointer将指针从floatArrayinputForFunction ,但我不确定如何实现它。 Just for your information, one way I'm thinking of is to use withUnsafePointer method directly: 仅供参考,我正在考虑的一种方法是直接使用withUnsafePointer方法:

var floatArray: [Float] = try originalHDF5DataSet.read()
var inputForFunction = UnsafeMutablePointer<Float>.allocate(capacity: Int(sizeOfArray))
withUnsafePointer(to: &floatArray[0]) { (ptr: UnsafePointer<Float>) in
  inputForFunction = UnsafeMutablePointer(mutating: ptr)
}

or the other way is to use withMemoryRebound (but the following didn't work): 或者另一种方式是使用withMemoryRebound (但以下不起作用):

var floatArray: [Float] = try originalHDF5DataSet.read()
var inputForFunction = UnsafeMutablePointer<Float>.allocate(capacity: Int(sizeOfArray))
withUnsafePointer(to: &floatArray) { (ptrDataArray: UnsafePointer<[Float]>) in
  inputForFunction = ptrDataArray.withMemoryRebound(to: inputForFunction.self, capacity: Int(sizeOfArray), { (ptr: UnsafePointer<[Float]>) -> UnsafeMutablePointer<Float> in
    return ptr[0]
  })
}

My question is 我的问题是

  • How to pass the address of floatArray 's data to inputForFunction ? 如何将floatArray数据的地址传递给inputForFunction
  • If I need to convert from UnsafePointer<[Float]> to Unsafe[Mutable]Pointer, how to do it? 如果我需要从UnsafePointer <[Float]>转换为Unsafe [Mutable]指针,该怎么做?
  • If needed, how to use withMemoryRebound for this purpose? 如果需要,如何使用withMemoryRebound用于此目的? Can I assign the address/value to inputForFunction inside the closure? 我可以将地址/值分配给闭包内的inputForFunction吗?
  • When I checked the addresses of floatArray and floatArray[0] , they were different (This seems different from C/C++). 当我检查floatArrayfloatArray[0]的地址时,它们是不同的(这似乎与C / C ++不同)。 Which address should be passed to inputForFunction ? 应该将哪个地址传递给inputForFunction

You can find many articles explaining how you can get Unsafe(Mutable)Pointer<Float> from [Float] . 您可以找到许多文章,解释如何从[Float]获取Unsafe(Mutable)Pointer<Float> Some of them answer some of your questions. 他们中的一些人回答了你的一些问题。 Try find them later. 稍后尝试找到它们。

  • How to pass the address of floatArray's data to inputForFunction? 如何将floatArray数据的地址传递给inputForFunction?

    You usually use the Array's methods withUnsafeBufferPointer or withUnsafeMutableBufferPointer . 您通常使用Array的方法withUnsafeBufferPointerwithUnsafeMutableBufferPointer You can get an Unsafe(Mutable)BufferPointer<Element> inside the closure parameter, which contains an Unsafe(Mutable)Pointer<Element> as its baseAddress property. 您可以在closure参数中获取一个Unsafe(Mutable)BufferPointer<Element> ,它包含一个Unsafe(Mutable)Pointer<Element>作为其baseAddress属性。

     var floatArray: [Float] = try originalHDF5DataSet.read() floatArray.withUnsafeBufferPointer {unsafeBufferPointer in let inputForFunction = unsafeBufferPointer.baseAddress //`unsafeBufferPointer` (including its `baseAddress`) is valid only in this closure. //So, do not pass `inputForFunction` outside of the closure, use it inside. //... } 
  • If I need to convert from UnsafePointer<[Float]> to Unsafe[Mutable]Pointer, how to do it? 如果我需要从UnsafePointer <[Float]>转换为Unsafe [Mutable]指针,该怎么做?

    When you find something like UnsafePointer<[Float]> , then you are going the wrong way. 当你发现像UnsafePointer<[Float]>这样的东西时,你就会走错路。 In Swift, Array is a hidden struct which may contain (multi-level) indirect reference to its elements. 在Swift中, Array是一个隐藏的结构,它可能包含对其元素的(多级)间接引用。 You usually have no need to use UnsafePointer<Array<Float>> . 您通常不需要使用UnsafePointer<Array<Float>>

  • If needed, how to use withMemoryRebound for this purpose? 如果需要,如何使用withMemoryRebound用于此目的? Can I assign the address/value to inputForFunction inside the closure? 我可以将地址/值分配给闭包内的inputForFunction吗?

    When you have an Array of AType and want to pass it as an Unsafe(Mutable)Pointer<AnotherType> , you may utilize withMemoryRebound . 如果您有一个AType数组并希望将其作为Unsafe(Mutable)Pointer<AnotherType> ,您可以使用withMemoryRebound But in your case, you only need to work with Float , so withMemoryRebound may not be needed for your purpose. 但在您的情况下,您只需要使用Float ,因此可能不需要withMemoryRebound用于您的目的。

  • When I checked the addresses of floatArray and floatArray[0], they were different (This seems different from C/C++). 当我检查floatArray和floatArray [0]的地址时,它们是不同的(这似乎与C / C ++不同)。 Which address should be passed to inputForFunction? 应该将哪个地址传递给inputForFunction?

    None. 没有。 As I wrote above, address of floatArray is just pointing somewhere which contains a hidden struct, so it's completely useless for your purpose. 正如我上面所写, floatArray的地址只是指向一个包含隐藏结构的地方,所以它对你的目的来说完全没用。 And address of floatArray[0] is neither guaranteed to be the address of the first element of the whole content. 并且floatArray [0]的地址既不保证是整个内容的第一个元素的地址。 Swift may create a temporal region which contains only one element, and passing the address of the temporal region. Swift可以创建仅包含一个元素的时间区域,并传递时间区域的地址。


By the way, do you really need to convert your [Float] to Unsafe(Mutable)Pointer<Float> ? 顺便说一句,你真的需要将[Float]转换为Unsafe(Mutable)Pointer<Float>吗?

If your functions' signature is something like this: 如果你的函数的签名是这样的:

func takingUnsafePointer(_ pointer: UnsafePointer<Float>)

You can call it like: 你可以这样称呼它:

takingUnsafePointer(floatArray)
//In this case `floatArray` can be a `let` constant.

Or else, if the function signature is: 否则,如果函数签名是:

func takingUnsafeMutablePointer(_ pointer: UnsafeMutablePointer<Float>)

Call it as: 称之为:

takingUnsafeMutablePointer(&floatArray)
//In this case `floatArray` needs to be a `var`, not `let`.

Remember, in both cases, the passed pointer is valid only while the function call. 请记住,在这两种情况下,传递的指针仅在函数调用时有效。 You should not export the pointer somewhere else. 您不应该将指针导出到其他位置。

Array type have withUnsafeBufferPointer method. Array类型具有withUnsafeBufferPointer方法。

This method accept closure with UnsafeBufferPointer which is like UnsafePointer<[Float]> you're asking for. 这个方法接受UnsafeBufferPointer闭包,就像你要求的UnsafePointer<[Float]>

In you need UnsafePointer to the start of Array you can use baseAddress property of UnsafeBufferPointer . 在你需要UnsafePointer到数组的开始,你可以使用baseAddress财产UnsafeBufferPointer

Example code: 示例代码:

let bufferPointer: UnsafeBufferPointer<Float> = floatArray.withUnsafeBufferPointer { bufferPointer in
    return bufferPointer
}

or 要么

let baseAddress: UnsafePointer<Float> = floatArray.withUnsafeBufferPointer { bufferPointer in
    return bufferPointer.baseAddress
}

EDIT : Or if it's function just passing &floatArray may work. 编辑 :或者如果它的功能只是传递&floatArray可能会工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM