Working with UnsafeMutablePointer array - ios

I'm trying to work with Brad Larson's splendid GPUImage framework, and I'm struggling to process the cornerArray returned by the GPUImageHarrisCornerDetectionFilter.
The corners are returned as an array of GLFloat in an UnsafeMutablePointer - and I would like to convert that to an array of CGPoint
I've tried allocating space for the memory
var cornerPointer = UnsafeMutablePointer<GLfloat>.alloc(Int(cornersDetected) * 2)
but the data doesn't seem to make any sense - either zero or 1E-32
I found what looked like the perfect answer how to loop through elements of array of <UnsafeMutablePointer> in Swift and tried
filter.cornersDetectedBlock = {(cornerArray:UnsafeMutablePointer<GLfloat>, cornersDetected:UInt, frameTime:CMTime) in
crosshairGenerator.renderCrosshairsFromArray(cornerArray, count:cornersDetected, frameTime:frameTime)
for floatData in UnsafeBufferPointer(start: cornerArray, count: cornersDetected)
{
println("\(floatData)")
}
but the compiler didn't like the UnsafeBufferPointer - so I changed it to UnsafeMutablePointer, but it didn't like the argument list.
I'm sure this is nice and simple, and it sounds like something other people must have had to do - so what's the solution?

The UnsafeMutablePointer<GLfloat> type translated from C can have its elements accessed via a subscript, just like a normal array. To achieve your goal of converting these to CGPoints, I'd use the following code:
filter.cornersDetectedBlock = { (cornerArray:UnsafeMutablePointer<GLfloat>, cornersDetected:UInt, frameTime:CMTime) in
var points = [CGPoint]()
for index in 0..<Int(cornersDetected) {
points.append(CGPoint(x:CGFloat(cornerArray[index * 2]), y:CGFloat(cornerArray[(index * 2) + 1])))
}
// Do something with these points
}
The memory backing cornerArray is allocated immediately before the callback is triggered, and deallocated immediately after it. Unless you copy these values over in the middle of the block, as I do above, I'm afraid that you'll leave yourself open to some nasty bugs. It's also easier to convert to the correct format at that point, anyway.

I have found a solution - and it's simple. The answer was here https://gist.github.com/kirsteins/6d6e96380db677169831
var dataArray = Array(UnsafeBufferPointer(start: cornerArray, count: Int(cornersDetected) * 2))

Try this :
var cornerPointer = UnsafeMutablePointer<GLfloat>.alloc(Int(cornersDetected) * 2)
filter.cornersDetectedBlock = {(cornerArray:UnsafeMutablePointer<GLfloat>, cornersDetected:UInt, frameTime:CMTime) in
crosshairGenerator.renderCrosshairsFromArray(cornerArray, count:cornersDetected, frameTime:frameTime)
for i in 0...cornersDetected
{
print("\(cornerPointer[i])")
}

Related

Converting Objective-C malloc to Swift

I am working on a project that was written in Objective-C and needs to be updated to Swift. We use a C file for transferring data.
Here is the code I was given in Objective-C:
- (NSData *)prepareEndPacket {
UInt8 *buff_data;
buff_data = (uint8_t *)malloc(sizeof(uint8_t)*(PACKET_SIZE+5));
// Call to C File
PrepareEndPacket(buff_data);
NSData *data_first = [NSData dataWithBytes:buff_data length:sizeof(uint8_t)*(PACKET_SIZE+5)];
return data_first;
}
In the C .h file I have this for reference:
#define PACKET_SIZE ((uint32_t)128)
I can not seem to find a good way of converting this to Swift. Any help would be appreciated.
malloc and free actually work fine in Swift; however, the UnsafeMutablePointer API is more "native". I'd probably use Data's bytesNoCopy for better performance. If you want, you can use Data(bytes:count:), but that will make a copy of the data (and then you need to make sure to deallocate the pointer after making the copy, or you'll leak memory, which is actually a problem in the Objective-C code above since it fails to free the buffer).
So, something like:
func prepareEndPacket() -> Data {
let count = PACKET_SIZE + 5
let buf = UnsafeMutablePointer<UInt8>.allocate(capacity: count)
PrepareEndPacket(buf)
return Data(bytesNoCopy: buf, count: count, deallocator: .custom { ptr, _ in
ptr.deallocate()
})
}
By using bytesNoCopy, the Data object returned is basically a wrapper around the original pointer, which will be freed by the deallocator when the Data object is destroyed.
Alternatively, you can create the Data object from scratch and get a pointer to its contents to pass to PrepareEndPacket():
func prepareEndPacket() -> Data {
var data = Data(count: PACKET_SIZE + 5)
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
PrepareEndPacket(ptr)
}
return data
}
This is slightly less efficient, since the Data(count:) initializer will initialize all the Data's bytes to zero (similar to using calloc instead of malloc), but in many cases, that may not make enough of a difference to matter.

Efficiently copying Swift Array to memory buffer for iOS Metal

I am writing an iOS application using Apple's new Metal framework. I have an array of Matrix4 objects (see Ray Wenderlich's tutorial) that I need to pass in to a shader via the MTLDevice.newBufferWithLength() method. The Matrix4 object is leveraging Apple's GLKit (it contains a GLKMatrix4 object).
I'm leveraging instancing with the GPU calls.
I will later change this to a struct which includes more data per instance (beyond just the Matrix4 object.
How can I efficiently copy the array of [Matrix4] objects into this buffer?
Is there a better way to do this? Again, I'll expand this to use a struct with more data in the future.
Below is a subset of my code:
let sizeofMatrix4 = sizeof(Float) * Matrix4.numberofElements()
// This returns an array of [Matrix4] objects.
let boxArray = createBoxArray(parentModelViewMatrix)
let sizeOfUniformBuffer = boxArray.count * sizeOfMatrix4
var uniformBuffer = device.newBufferWithLength(sizeofUniformBuffer, options: .CPUCacheModeDefaultCache)
let bufferPointer = uniformBuffer?.contents()
// Ouch - way too slow. How can I optimize?
for i in 0..<boxArray.count
{
memcpy(bufferPointer! + (i * sizeOfMatrix4), boxArray[i].raw(), sizeOfMatrix4)
}
renderEncoder.setVertexBuffer(uniformBuffer, offset: 0, atIndex: 2)
Note:
The boxArray[i].raw() method is defined as this in the Objective-C code:
- (void *)raw {
return glkMatrix.m;
}
You can see I'm looping through each array object and then doing a memcpy. I did this since I was experiencing problems treating the array as a contiguous set of memory.
Thanks!
A Swift Array is promised to be contiguous memory, but you need to make sure it's really a Swift Array and not secretly an NSArray. If you want to be completely certain, use a ContiguousArray. That will ensure contiguous memory even if the objects in it are bridgeable to ObjC. If you want even more control over the memory, look at ManagedBuffer.
With that, you should be using newBufferWithBytesNoCopy(length:options:deallocator) to create a MTL buffer around your existing memory.
I've done this with an array of particles that I pass to a compute shader.
In a nutshell, I define some constants and declare a handful of mutable pointers and a mutable buffer pointer:
let particleCount: Int = 1048576
var particlesMemory:UnsafeMutablePointer<Void> = nil
let alignment:UInt = 0x4000
let particlesMemoryByteSize:UInt = UInt(1048576) * UInt(sizeof(Particle))
var particlesVoidPtr: COpaquePointer!
var particlesParticlePtr: UnsafeMutablePointer<Particle>!
var particlesParticleBufferPtr: UnsafeMutableBufferPointer<Particle>!
When I set up the particles, I populate the pointers and use posix_memalign() to allocate the memory:
posix_memalign(&particlesMemory, alignment, particlesMemoryByteSize)
particlesVoidPtr = COpaquePointer(particlesMemory)
particlesParticlePtr = UnsafeMutablePointer<Particle>(particlesVoidPtr)
particlesParticleBufferPtr = UnsafeMutableBufferPointer(start: particlesParticlePtr, count: particleCount)
The loop to populate the particles is slightly different - I now loop over the buffer pointer:
for index in particlesParticleBufferPtr.startIndex ..< particlesParticleBufferPtr.endIndex
{
[...]
let particle = Particle(positionX: positionX, positionY: positionY, velocityX: velocityX, velocityY: velocityY)
particlesParticleBufferPtr[index] = particle
}
Inside the applyShader() function, I create a copy of the memory which is used as both the input and output buffer:
let particlesBufferNoCopy = device.newBufferWithBytesNoCopy(particlesMemory, length: Int(particlesMemoryByteSize),
options: nil, deallocator: nil)
commandEncoder.setBuffer(particlesBufferNoCopy, offset: 0, atIndex: 0)
commandEncoder.setBuffer(particlesBufferNoCopy, offset: 0, atIndex: 1)
...and after the shader has run, I put the shared memory (particlesMemory) back into the buffer pointer:
particlesVoidPtr = COpaquePointer(particlesMemory)
particlesParticlePtr = UnsafeMutablePointer(particlesVoidPtr)
particlesParticleBufferPtr = UnsafeMutableBufferPointer(start: particlesParticlePtr, count: particleCount)
There's an up to date Swift 2.0 version of this at my GitHub repo here
Obviously the point of using shared memory and MTLDevice.makeBuffer(bytesNoCopy:...) is to avoid redundant memory copies. Therefore, ideally we look for a design that allows us to easily manipulate the data after it's already been loaded into the MTLBuffer object.
After researching this for a while, I've decided to try and create a semi-generic solution to allow for simplified allocation of page-aligned memory, loading your content into that memory, and subsequently manipulating your items in that shared memory block.
I've created a Swift array implementation called PageAlignedArray that matches the interface and functionality of the built-in Swift array, but always resides on page-aligned memory, and so can be very easily made into an MTLBuffer. I've also added a convenience method to directly convert PageAlignedArray into a Metal buffer.
Of course, you can continue to mutate your array afterwards and your updates will be automatically available to the GPU courtesy of the shared-memory architecture. However, keep in mind that you must regenerate your MTLBuffer object whenever the array's length changes.
Here's a quick code sample:
var alignedArray : PageAlignedContiguousArray<matrix_double4x4> = [matrixTest, matrixTest]
alignedArray.append(item)
alignedArray.removeFirst() // Behaves just like a built-in array, with all convenience methods
// When it's time to generate a Metal buffer:
let testMetalBuffer = device?.makeBufferWithPageAlignedArray(alignedArray)
The sample uses matrix_double4x4, but the array should work for any Swift value types. Please note that if you use a reference type (such as any kind of class), the array will contain pointers to your elements and so won't be usable from your GPU code.

In Swift, how do I set every element inside an array to nil?

var roomsLiveStates = [Firebase?]()
for ref in roomsLiveStates {
if ref != nil {
ref = nil
}
}
}
This doesn't seem to work.
You can just set each to nil:
for index in 0 ..< roomsLiveStates.count {
roomsLiveStates[index] = nil
}
As The Swift Programming Language says in its Control Flow discussion of for syntax:
This example prints the first few entries in the five-times-table:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
... In the example above, index is a constant whose value is automatically set at the start of each iteration of the loop. As such, it does not have to be declared before it is used. It is implicitly declared simply by its inclusion in the loop declaration, without the need for a let declaration keyword.
As this says, the index is a constant. As such, you can not change its value.
You can also use a map:
roomsLiveStates = roomsLiveStates.map { _ in nil }
This is less code and a good habit to get into for other cases where you may want to create a processed copy of an array without mutating the original.
if you want to set each element in array to a numberic value(int, float, double ...), you can try vDSP framework.
Please check this:
https://developer.apple.com/documentation/accelerate/vdsp/vector_clear_and_fill_functions
You can also just reassign the whole array to one that only contains nil like:
roomsLiveStates = [Firebase?](count: roomsLiveStates.count, repeatedValue: nil)
Although now that I think about it, this doesn't seem so good, because (probably?) new memory gets allocated which is not fast at all
EDIT: I just checked and found that using .map is a lot slower in Debug builds. However on Release builds, .map is about 20% faster. So I suggest using the .map version (which also is quiet a bit prettier ;)):
array = array.map { _ in nil }
Iterating the array to map it, will result in poor performance (iteration + new allocation).
Allocating the array all over (init(repeating...) is better, but still allocates a new array, very costly.
The best way would be to zero out the data without allocating it again, and as every C programmer knows, that's why we have bzero and memset for.
It won't matter much for small arrays in a non repeating action, and as long as you remember it - using the smallest code possible could make sense, so sometimes using map or init makes sense.
Final note on the test - map and init use multiple allocations of the same size in this test, which makes allocation allot faster than in real world usage.
In general, memory allocation is not your friend, it is a time consuming process that may result in having to defragment the heap, calling kernel code to allocate new virtual memory, and also must use locks and/or memory barriers.
import Foundation
guard CommandLine.argc == 2, let size = Int(CommandLine.arguments[1]),size > 0 else {
fatalError("Usage: \(CommandLine.arguments[0]) {size}\nWhere size > 0")
}
var vector = [Int].init(repeating: 2, count: size)
let ITERATIONS = 1000
var start:Date
var end:Date
start = Date()
for _ in 0..<ITERATIONS {
vector = vector.map({ _ in return 0 })
}
end = Date()
print("Map test: \(end.timeIntervalSince(start)) seconds")
start = Date()
for _ in 0..<ITERATIONS {
vector = [Int].init(repeating: 0, count: size)
}
end = Date()
print("init(repeating:,count:) test: \(end.timeIntervalSince(start)) seconds")
start = Date()
for _ in 0..<ITERATIONS {
let size = MemoryLayout.size(ofValue: vector[0]) * vector.count // could optimize by moving out the loop, but that would miss the purpose
vector.withUnsafeMutableBytes { ptr in
let ptr = ptr.baseAddress
bzero(ptr, size)
}
}
end = Date()
print("bzero test: \(end.timeIntervalSince(start)) seconds")
Results when running with an array of 5,000,000 items size (M1 Mac), compiled with optimizations:
Map test: 5.986680030822754 seconds
init(repeating:,count:) test: 2.291425108909607 seconds
bzero test: 0.6462910175323486 seconds
Edit:
Just realized it's also to initialize the memory using the initializeMemory(...) method.
Something like:
_ = vector.withUnsafeMutableBytes { ptr in
ptr.initializeMemory(as: Int.self, repeating: 0)
}
The performance is virtually the same as with bzero, and it is pure swift and shorter.

Swift automatically creating temporary dictionaries

I'm working with a datasource for a UITableView where I need an array with dictionaries.
I tried making an array, and filling it with dictionaries in a for loop like this.
temporaryDataDict = [:]
temporaryDataDict = ["name":stockName, "ticker":ticker, "lastPrice":lastPrice, "purchasePrice":purchasePrice, "weight":weight, "daysHeld":daysHeld]
temporaryDataArray.append(temporaryDataDict)
But of course, when I start filling my tableView with the dataSource. I end up for 23 of the exact same dictionaries (the last one in the for loop).
This is of course, because it's changing the dictionary every time.
I havn't been able to find a way to keep the data in the dictionaries, or programatically make a new dictionary every time (since they need a new name otherwise it'll overwrite the data).
So how can I programatically make dictionaries everytime a for loop runs, then get the keys & values of these dictionaries?
or am I going about this completely wrong?
If it helps, here's the kind of data I'm working with.
I have a stock (or item) with 6 properties. So I think it makes the most sense to have an array where every item in the array is the "stock" as a dictionary that contains the 6 properties.
So is it possible to make swift automatically create these dictionaries for me? Since I don't know the amount of dictionaries needed.
PS.
I know this is what CoreData is for. I'm using these arrays and Dictionaries to later fill in my CoreData.
If the above isn't possible I am aware that I can probably create a new CoreData entity to accomplish what I want, but it doesn't seem like the best way to go about it.
Any help would be greatly appreciated! Thanks
I don't believe that a dictionary is the best sort of data structure to use in this case. Since typically a dictionary is composed of a unique key and a value.
I have edited this answer. Originally I suggested creating a class containing a property for each record field. Then I figured that this could be done using a tuple via a typealias for each record. Using a typealias gets around an issue related to creating arrays of tuples.
ETA: However please read the comments because Zaph who knows more about this than me reckons that using a Class is a stronger solution.
This is my tuple based solution. Most of what follows is just about quickly creating some dummy data:
typealias StockRecord = (stockName:String, ticker: String, lastPrice: Double, purchasePrice: Double, weight: Double, daysHeld: Int)
var temporaryDataArray = [StockRecord]()
// use a loop to create dummy records and add each to the array
// rough and ready - just to test the solution
var loopCounter: Int
for loopCounter = 0; loopCounter <= 23; loopCounter++ {
//some dummy field values for each record
var stockName = "stockName" + ("\(loopCounter)")
var ticker = "ticker" + ("\(loopCounter)")
var lastPrice = Double(loopCounter)
var purchasePrice = Double(loopCounter)
var weight = Double(loopCounter)
var daysHeld = loopCounter
var newRecord = (stockName, ticker, lastPrice, purchasePrice, weight, daysHeld)
temporaryDataArray.append(newRecord)
}
ETA: Iterate over the array - eg:
for recordEntry in temporaryDataArray {
var a = recordEntry.stockName
var b = recordEntry.ticker
// etc
}
Or with enumeration - eg:
for (count,recordEntry) in enumerate(temporaryDataArray) {
println("\(count) \(recordEntry)")
}
Output:
0 (stockName0, ticker0, 0.0, 0.0, 0.0, 0)
1 (stockName1, ticker1, 1.0, 1.0, 1.0, 1)
2 (stockName2, ticker2, 2.0, 2.0, 2.0, 2)
3 (stockName3, ticker3, 3.0, 3.0, 3.0, 3)
etc

Write float values to Pointer Array of float in C# (unsafe or safe) using AVAudioPCMBuffer

While I'm not very comfortable using the unsafe context in C#, I do understand that I may have to sometimes use it.
To get right to it, in order to write byte values to an IntPtr, I could write the below from a safe context:
for (int i = 0; i < counter; i++)
{
System.Runtime.InteropServices.Marshal.WriteByte (data, i, 0);
}
How can i do the same from an unsafe context?
To be more specific I am actually trying to write float values to a an Intptr variable that is actually a float array pointer. I dont see any overloads capable of handling writing float data using System.Runtime.InteropServices from a safe context.
I tried the below but get the error:
malloc: *** error for object 0x17e9eca4: incorrect checksum for freed object - object was probably modified after being freed.
var data = (float*)buffer.FloatChannelData;
for (int i = 0; i < buffer.FrameLength; i++)
{
data [i] = 0.0f;
*data++ = 0.0f; // also tried this but got the same error
}
Your help is much appreciated.
Additional details:
I am trying to write data to AudioPCMBuffers in Xamarin.IOS. I thought the buffer contained a an array of float but as pointed by #Passant in the comments it actually contains an array of pointers to array of framelength floats. he same premise applies, whether from a safe or unsafe context I would like to be able to write data to the buffers. An example will be very helpful. Thanks and apologies for the confusion
Rolf's answer for the question is here:
Try this: https://gist.github.com/rolfbjarne/dc947383a6c9172bc664
It will mix mic input with a sine wave.

Resources