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
). I'm new to UnsafePointer, so I need someone's help.
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. Just for your information, one way I'm thinking of is to use withUnsafePointer
method directly:
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):
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
floatArray
's data to inputForFunction
?withMemoryRebound
for this purpose? Can I assign
the address/value to inputForFunction
inside the closure?floatArray
and floatArray[0]
, they were different (This seems different from C/C++). Which address should be passed to inputForFunction
?You can find many articles explaining how you can get Unsafe(Mutable)Pointer<Float>
from [Float]
. Some of them answer some of your questions. Try find them later.
How to pass the address of floatArray's data to inputForFunction?
You usually use the Array's methods withUnsafeBufferPointer
or withUnsafeMutableBufferPointer
. You can get an Unsafe(Mutable)BufferPointer<Element>
inside the closure parameter, which contains an Unsafe(Mutable)Pointer<Element>
as its baseAddress
property.
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?
When you find something like UnsafePointer<[Float]>
, then you are going the wrong way. In Swift, Array
is a hidden struct which may contain (multi-level) indirect reference to its elements. You usually have no need to use UnsafePointer<Array<Float>>
.
If needed, how to use withMemoryRebound for this purpose? Can I assign the address/value to inputForFunction inside the closure?
When you have an Array of AType
and want to pass it as an Unsafe(Mutable)Pointer<AnotherType>
, you may utilize withMemoryRebound
. But in your case, you only need to work with Float
, so withMemoryRebound
may not be needed for your purpose.
When I checked the addresses of floatArray and floatArray[0], they were different (This seems different from C/C++). Which address should be passed to 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. And address of floatArray[0] is neither guaranteed to be the address of the first element of the whole content. Swift may create a temporal region which contains only one element, and passing the address of the temporal region.
By the way, do you really need to convert your [Float]
to 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.