let url = URL(fileURLWithPath: "test.wav")
let data = try Data(contentsOf: url)
let fb = (data as NSData).bytes
let fbytes = fb.assumingMemoryBound(to: Int8.self)
fbytes.deallocate() // Crash.
How to properly do this? I need to free manually because I'm using this with a C library that streams audio in a thread so something like withUnsafePointer is not an option.
You cannot deallocate the bytes of an NSData, you must let it be freed by dropping the reference to the NSData. Additionally, NSData.bytes is unsafe in Swift and you must never ever use it.
Can you please elaborate on what your actual problem is?
Oh, I see, I've scene that being suggested in a stackoverflow post so decided to use it.
So I just basically want to get the data content as a UnsafePointer, Send it to the C function, And then I manually later create a function that deallocates it, Something like
class Streamer {
var buffer: UnsafePointer<Int8>
required init(buffer: UnsafePointer<Int8>) {
self.buffer = buffer
}
func destroy() {
// Deallocate the pointer here.
}
static func fromMemory(data: Data) -> Streamer {
var buffer: UnsafePointer<Int8> = ... // How to create the buffer here.
CLibStream(buffer)
return self.init(buffer: buffer)
}
}
var buffer: UnsafePointer<Int8> = UnsafeMutablePointer<Int8>.allocate(capacity: whatever)
to allocate the buffer, and
buffer.deallocate()
to deallocate it. However, this is extremely unsafe. Is it possible for you to bound the execution time so that you can use a withUnsafePointer function?
Sadly there is no way to do that.
So if I'll use the allocating way, How would I do it with the Data type? I'm guessing the size would come from data.count, But how would we extract the content of data and give it to the pointer?
C:\Users\mohamed\projects\swift_synthizer\Sources\synthizer\stream.swift:21:9: error: instance method 'initialize(from:)' requires the types 'Int8' and 'UInt8' be equivalent
buffer.initialize(from: data)
^
Swift.UnsafeMutablePointer:10:17: note: where 'Pointee' = 'Int8', 'C.Element' = 'UInt8'
public func initialize<C>(from source: C) where Pointee == C.Element, C : Collection
^
Here's the code I use
public static func fromMemory(data: Data) throws -> StreamHandle {
var handle = syz_Handle()
let buffer = UnsafeMutablePointer<Int8>.allocate(capacity: data.count)
buffer.initialize(from: data)
return self.init(handle: handle, buffer: fbytes)
}
}
You need to change Int8 to UInt8. Also, UnsafeMutablePointer.initialize(from:) is deprecated, so you might want to use an UnsafeMutableBufferPointer instead, i.e:
let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: data.count)
_ = buffer.initialize(from: data)