AudioToolbox, C-function pointers, and Swift - swift

I'm working, tentatively, with the AudioToolbox API using Swift 2.0 and Xcode 7b6. The API uses a lot of c-language constructs, including function pointers. This is my first time working with commands like withUnsafeMutablePointer and unsafeBitCast. I am looking for a reality check to make sure that I am not way off base in what I am doing.
For example, to open a file stream, you use the following function:
func AudioFileStreamOpen(
_ inClientData: UnsafeMutablePointer<Void>
, _ inPropertyListenerProc: AudioFileStream_PropertyListenerProc
, _ inPacketsProc: AudioFileStream_PacketsProc
, _ inFileTypeHint: AudioFileTypeID
, _ outAudioFileStream: UnsafeMutablePointer<AudioFileStreamID>) -> OSStatus
Just the type signature of the function makes me start to sweat.
At any rate, the inClientData parameter needs to be an UnsafeMutablePointer<Void>, and the pointer will point to an instance of the same class I am working in. In other words, it needs to be a pointer to self. My approach is to call the function using withUnsafeMutablePointer like this:
var proxy = self
let status = withUnsafeMutablePointer(&proxy) {
AudioFileStreamOpen($0, AudioFileStreamPropertyListener
, AudioFileStreamPacketsListener, 0, &audioFileStreamID)
}
My first question is whether or not I'm using withUnsafeMutablePointer correctly here. I wasn't sure how to get a pointer to self - just writing &self doesn't work, because self is immutable. So I declared proxy as a variable and passed a reference to that, instead. I don't know if this will work or not, but it was the best idea I came up with.
Next, AudioFileStreamPropertyListener and AudioFileStreamPacketsListener are C callback functions. They each get passed the pointer to self that I created using withUnsafeMutablePointer in AudioFileStreamOpen. The pointer is passed in as an UnsafeMutablePointer<Void>, and I need to cast it back to the type of my class (AudioFileStream). To do that, I believe I need to use unsafeBitCast. For example, here is AudioFileStreamPropertyListener:
let AudioFileStreamPropertyListener: AudioFileStream_PropertyListenerProc
= { inClientData, inAudioFileStreamID, inPropertyID, ioFlags in
let audioFileStream = unsafeBitCast(inClientData, AudioFileStream.self)
audioFileStream.didChangeProperty(inPropertyID, flags: ioFlags)
}
That compiles fine, but again I'm not sure if I'm using unsafeBitCast correctly, or if that is even the correct function to be using in this kind of situation. So, is unsafeBitCast the correct way to take an UnsafeMutablePointer<Void> and cast it to a type that you can actually use inside of a C function pointer?

It's interesting that the inClientData "context" param is bridged as UnsafeMutablePointer, since I doubt the AudioToolbox APIs will modify your data. It seems it would be more appropriate if they'd used COpaquePointer. Might want to file a bug.
I think your use of withUnsafeMutablePointer is wrong. The pointer ($0) will be the address of the variable proxy, not the address of your instance. (You could say $0.memory = [a new instance] to change it out for a different instance, for example. This is a bit confusing because its type is UnsafeMutablePointer<MyClass> — and in Swift, the class type is itself a pointer/reference type.)
I was going to recommend you use Unmanaged / COpaquePointer, but I tested it, and realized this does exactly the same thing as unsafeAddressOf(self)!
These are equivalent:
let data = UnsafeMutablePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
let data = unsafeAddressOf(self)
And these are equivalent:
let obj = Unmanaged<MyClass>.fromOpaque(COpaquePointer(data)).takeUnretainedValue()
let obj = unsafeBitCast(data, MyClass.self)
While the Unmanaged approach makes logical sense, I think you can see why it might be prefereable to use unsafeAddressOf/unsafeBitCast :-)
Or, you might consider an extension on Unmanaged for your own convenience:
extension Unmanaged
{
func toVoidPointer() -> UnsafeMutablePointer<Void> {
return UnsafeMutablePointer<Void>(toOpaque())
}
static func fromVoidPointer(value: UnsafeMutablePointer<Void>) -> Unmanaged<Instance> {
return fromOpaque(COpaquePointer(value))
}
}
Then you can use:
let data = Unmanaged.passUnretained(self).toVoidPointer()
let obj = Unmanaged<MyClass>.fromVoidPointer(data).takeUnretainedValue()
Of course, you will need to ensure that your object is being retained for the duration that you expect it to be valid in callbacks. You could use passRetained, but I would recommend having your top-level controller hold onto it.
See some related discussion at https://forums.developer.apple.com/thread/5134#15725.

Related

Passing a class type by reference

So I want I my base tableView, upon which I've derived others, to centralize drag-n-drop operations. Each of these tableViews have a distinct array controller as its dataSource, with each item class conforming to pasteboard reading and writing protocols.
But I'm stuck on its setup
override func mouseDragged(with event: NSEvent) {
let arrayController = self.dataSource as! NSArrayController
let itemClass = arrayController.objectClass
let objects = arrayController.arrangedObjects as! [itemClass]
let indexSet = self.selectedRowIndexes
var items = [NSDraggingItem]()
for index in indexSet {
let item = NSDraggingItem.init(pasteboardWriter: objects[index])
items.append(item)
}
self.beginDraggingSession(with: items, event: event, source: self)
}
as I get an error ?
Short Answer: This just isn't how Swift works, cast (as? or as!) to an appropriate compile time type – in this case from the use of objects in NSDraggingItem.init(pasteboardWriter: objects[index]) that is probably [NSPasteBoardWriting]
Longer Answer:
You may have just made a simple error, we all do sometimes, and the short answer is enough. But if you are wondering why your code isn't accepted maybe this will help and hopefully not confuse!
What you are trying to do is a form of dynamic typing, you set itemClass to a type that at compile time nothing is known about except that it is some class type.
At its core Swift is essentially a statically typed language, it works by either knowing everything about the type of something, e.g. when something is declared to have a particular reference or value type; by knowing something about the type, e.g. when something has a protocol type; or even nothing, e.g. when something is of unconstrained generic parameter type and in all these cases what can be done is largely limited by this knowledge.
Variable types are not supported; while there are less specific types, e.g. the AnyClass in the example, operations specific to the actual runtime type of something cannot be performed until a cast to that specific (compile time known) type is made (with as? or as!)
Swift does support some dynamic typing features, notably in its support for parts of Objective-C – which has both statically and dynamically typed parts; but these do not give you what you are trying to do here, that is cast to a type unknown until runtime.
You probably know Objective-C, a simple example of how the two languages differ in static/dynamic approach is what happens when a method/function is called. For Objective-C method dispatch is dynamic, the compiled code performs a search for the implementation of the method and that search may fail resulting in a runtime error and abort. In Swift (excluding its interworking with Objective-C) when a function is called the compiled code does not search, the implementation is known to exist at compile time and there can by no runtime error and abort.
To do what you are attempting you need to determine at design time what type you need to perform the desired operation (construct an NSDraggingItem in this case) and whether you either absolutely know or maybe know the value you have will at runtime conform to that type. If you absolutely know you can use the as! cast, which will abort execution if you are wrong, or you can use the as? which allows you to test for success and take appropriate action if you have something of unplanned type.
HTH
I will posit my own answer with the Sweeper's suggestion and CRD's excellent commentary.
The source objects, conform to the pasteboard writing protocol - NSPasteboardWriting; I mandate it. The target casting confirms this. My issue was a noob case of thinking objC, and cast at source vs target but enforcing just the same; I hope ;-).
override func mouseDragged(with event: NSEvent) {
let arrayController = self.dataSource as! NSArrayController
let objects = arrayController.arrangedObjects as! [NSPasteboardWriting]
let delegate = self.delegate as! NSViewController
let indexSet = self.selectedRowIndexes
var items = [NSDraggingItem]()
for index in indexSet {
let dragImage = (delegate.view.window?.windowController?.document as! Document).displayImage!
let item = NSDraggingItem.init(pasteboardWriter: objects[index])
item.setDraggingFrame(self.rect(ofRow: index), contents: dragImage)
item.draggingFrame = self.rect(ofRow: index)
items.append(item)
}
self.beginDraggingSession(with: items, event: event, source: self)
}

Understanding UnsafeMutablePointers and how to deal with them

Could anyone please explain or give a link to a good guide on UnsafeMutablePointers? I can't freaking understand how they work and how to modify them.
Here's an example.
I am migrating my custom video player to Swift from Objective-C.
In Objective-C I create MTAudioProcessingTapRef using a callbacks structure:
MTAudioProcessingTapCallbacks callbacks;
callbacks.clientInfo = (__bridge void *)(self);
callbacks.init = initTap;
// Init other fields of callbacks
MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PostEffects, &tap);
Here I cast retainable MyClass pointer to void pointer to use it as clientInfo later.
(__bridge T) op casts the operand to the destination type T. If T is a
non-retainable pointer type, then op must have a retainable object
pointer type.
Then tap gets initialized:
void initTap(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut)
{
*tapStorageOut = clientInfo;
}
Here I pass a pointer to self into tapStorageOut to grab self inside tap's callback function.
And then processing is performed:
void processTap(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut,
CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
{
MyClass *self = (__bridge MyClass *) MTAudioProcessingTapGetStorage(tap);
MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, NULL, numberFramesOut);
}
Now I have a few issues here.
I did found how to cast types into other types. Here are the functions:
func bridge<type : AnyObject>(object : type) -> UnsafeRawPointer
{
let unmanagedObject : Unmanaged = Unmanaged.passUnretained(object)
let unsafeMutableRawObject : UnsafeMutableRawPointer = unmanagedObject.toOpaque()
return UnsafeRawPointer(unsafeMutableRawObject)
}
func bridge<type : AnyObject>(pointer : UnsafeRawPointer) -> type
{
let unmanagedObject : Unmanaged<type> = Unmanaged<type>.fromOpaque(pointer)
let object : type = unmanagedObject.takeUnretainedValue()
return object
}
but I have zero understanding of what all of these letters do. Some explanation of this by one of you guys would be awesome.
Let's look at initTap function. Here I have a pointer A (tapStorageOut) that references a pointer B that references some data. I change pointer B to pointer C, which is my clientInfo. Clear as a sunny day.
Now, in Swift tapStorageOut is UnsafeMutablePointer now, whatever that thing is. And I have zero clue about how to deal with it.
In Objective-C when I process data I have a bufferListInOut variable which is a pointer to AudioBufferList structure.
In Swift however it has UnsafeMutablePointer type. So again, not understanding how UnsafeMutablePointers work prevents me from grabbing the data.
The main use of a pointer in Swift is working with C API and such. For the most part you should use reference semantics instead of pointers in Swift. That means using a class, when you pass a class instance around it automatically passes a reference instead of making a copy. Thus, it saves resources and any changes you make to a reference to the instance are reflected everywhere it is referenced. A Swift class is generally instantiated on the heap.
When you convert Objective-C to Swift pointers to objects are generally treated as references to those objects. Internally, a Swift reference is pretty much semantic sugar for a pointer.
Swift structures, on the other hand, have value semantics. They are generally instantiated on the stack and when you pass them around they are copied rather than passing a reference. The same goes when you mutate them, a new instance is created with the new values and it is swapped for the old instance. There are some tricks done where a struct will wrap a block of memory and hold a pointer to that memory. Thus a struct may have some reference semantics internally but try to avoid breaking the expectation of a struct's value being copied when it's passed around.
Some good reading:
Fundamentals of Callbacks for Swift Developers
Thinking in Swift, Part 3: Struct vs. Class
Lazy Initialization with Swift
I'd read these and take a good, hard look at your architecture before trying to use stuff like UnsafeMutablePointer. Yes, they are useful in some circumstances but they can be a pain to work with and are not necessary for most pure Swift tasks. Especially in a Swift API!

Syntactic Sugar Struct Reference in Swift?

In c++, one can introduce an alias reference as follows:
StructType & alias = lengthyExpresionThatEvaluatesToStuctType;
alias.anAttribute = value; // modify "anAttribute" on the original struct
Is there a similar syntactic sugar for manipulating a (value typed) struct in Swift?
Update 1: For example: Let say the struct is contained in a dictionary of kind [String:StructType], and that I like to modify several attributes in the the struct myDict["hello"]. I could make a temporary copy of that entry. Modify the copy, and then copy the temporary struct back to the dictionary, as follows:
var temp = myDict["hello"]!
temp.anAttribute = 1
temp.anotherAttribute = "hej"
myDict["hello"] = temp
However, if my function has several exit points I would have to write myDict["hello"] = temp before each exit point, and it would therefore be more convinient if I could just introduce and alias (reference) for myDict["hello"] , as follows:
var & alias = myDict["hello"]! // how to do this in swift ???
alias.anAttribute = 1
alias.anotherAttribute = "hej"
Update 2: Before down- or close- voting this question: Please look at Building Better Apps with Value Types in swift (from WWWDC15)!! Value type is an important feature of Swift! As you may know, Swift has borrowed several features from C++, and value types are maybe the most important feature of C++ (when C++ is compared to Java and such languages). When it comes to value types, C++ has some syntactic sugar, and my questions is: Does Swift have a similar sugar hidden in its language?. I am sure Swift will have, eventually... Please, do not close-vote this question if you do not understand it!
I have just read Deitel's book on Swift. While I'am not an expert (yet) I am not completely novel. I am trying to use Swift as efficient as possible!
Swift doesn't allow reference semantics to value types generally speaking, except when used as function parameters declared inout. You can pass a reference to the struct to a function that works on an inout version (I believe, citation needed, that this is implemented as a copy-write, not as a memory reference). You can also capture variables in nested functions for similar semantics. In both cases you can return early from the mutating function, while still guaranteeing appropriate assignment. Here is a sample playground that I ran in Xcode 6.3.2 and Xcode 7-beta1:
//: Playground - noun: a place where people can play
import Foundation
var str = "Hello, playground"
struct Foo {
var value: Int
}
var d = ["nine": Foo(value: 9), "ten": Foo(value: 10)]
func doStuff(key: String) {
let myNewValue = Int(arc4random())
func doMutation(inout temp: Foo) {
temp.value = myNewValue
}
if d[key] != nil {
doMutation(&d[key]!)
}
}
doStuff("nine")
d // d["nine"] has changed... unless you're really lucky
// alternate approach without using inout
func doStuff2(key: String) {
if var temp = d[key] {
func updateValues() {
temp.value = Int(arc4random())
}
updateValues()
d[key] = temp
}
}
doStuff2("ten")
d // d["ten"] has changed
You don't have to make the doMutation function nested in your outer function, I just did that to demonstrate the you can capture values like myNewValue from the surrounding function, which might make implementation easier. updateValues, however, must be nested because it captures temp.
Despite the fact that this works, based on your sample code, I think that using a class here (possibly a final class if you are concerned about performance) is really more idiomatic imperative-flavored Swift.
You can, if you really want to, get a raw pointer using the standard library function withUnsafeMutablePointer. You can probably also chuck the value into an inner class that only has a single member. There are also functional-flavored approaches that might mitigate the early-return issue.

Selector string from Swift function

Given a function reference, is there a way in Swift to get the name of that function as a string suitable for passing to NSSelectorFromString?
I'd like to wrap NSNotificationCenter's addObserver with a version that takes a function reference instead of a selector string:
addObserver(self, function: someCallback, name: "some notification", object: nil)
But addObserver takes a String selector argument.
You're reinventing an unnecessary wheel. NSNotificationCenter already has an observation method that takes a function (what Objective-C calls a "block"):
addObserverForName:object:queue:usingBlock:
So just use that.
I'd still like to find an answer to my original question, but based on #matt's suggestion, I'm currently using this extension:
extension NSNotificationCenter {
class func addObserver(function: (NSNotification!) -> (), name: String? = nil, object: AnyObject? = nil, queue: NSOperationQueue? = nil) {
defaultCenter().addObserverForName(name, object: object, queue: nil, usingBlock: function)
}
}
Since it implicitly uses defaultCenter() and provides defaults for object and queue, which I'd almost always pass nil for, it allows for a more succinct call:
NSNotificationCenter.addObserver(doSomething, name: "some notification")
I like that it links against the actual function (doSomething), rather than a string representation. It's not a general purpose extension, but I think it covers 90% of the cases where I register for notifications.
Edit: I'm leaving this here for interest, but it's way too complicated (got wrapped up in how the question was asked, rather than the goal). Beyond the existing block-based approach, there's also this handy extension to it.
I wouldn't do it this way. It's too limiting because it would exclude function literals (anonymous functions).
Instead, I would play this game:
Create an dictionary property mapping [String: Void -> ()] (string to function)
When you register a new function, make up a unique, random key and store the function you're passed in your dictionary with that key.
Register with the selector observer_dispatcher_<key> (or whatever prefix you like).
Implement resolveInstanceMethod: to dynamically create any observer_dispatcher_ method you're requested. They can all point to the same IMP, something like:
(assuming this is good Swift; I haven't tried it):
void _observer_dispatcher(self: AnyObject, _cmd: Selector) {
let name = // strip the leading stuff off of _cmd
if let f = self.dispatchTable[name] {
f()
}
}
(This is still pretty sloppy; I'll have to think about the correct correct impl more, but this is the direction I'd go in.)

Convert String to UnsafeMutablePointer<char_t> in Swift

I'm working with a third party c API I'm trying to call one of the functions with a simple string. Something like this:
some_c_func("aString");
I get a build error:
Type 'UnsafeMutablePointer<char_t>' does not conform to protocol 'StringLiteralConvertible'
I've seen some suggestions to use utf8 on String or similar conversions, which gets nearly there, but with the following error:
some_c_func("aString".cStringUsingEncoding(NSUTF8StringEncoding));
'UnsafePointer<Int8>' is not convertible to 'UnsafeMutablePointer<char_t>'
How can I create an UnsafeMutablePointer?
It all depends on what char_t is.
If char_t converts to Int8 then the following will work.
if let cString = str.cStringUsingEncoding(NSUTF8StringEncoding) {
some_c_func(strdup(cString))
}
This can be collapsed to
some_c_func(strdup(str.cStringUsingEncoding(NSUTF8StringEncoding)!))
WARNING! This second method will cause a crash if func cStringUsingEncoding(_:) returns nil.
Updating for Swift 3, and to fix memory leak
If the C string is only needed in a local scope, then no strdup() is needed.
guard let cString = str.cString(using: .utf8) else {
return
}
some_c_func(cString)
cString will have the same memory lifecycle as str (well similar at least).
If the C string needs to live outside the local scope, then you will need a copy. That copy will need to be freed.
guard let interimString = str.cString(using: .utf8), let cString = strdup(interimString) else {
return
}
some_c_func(cString)
//…
free(cString)
it may be simpler than that - many C APIs pass strings around as char * types, and swift treats these as unsafe.
try updating the C API (good) or hack it's header files (bad) to declare these as const char * instead.
in my experience this allows you to pass standard swift String types directly to the C API.
apparently a constant is required, in order to conform to the protocol.
I haven't tried passing strings like that, but I have a C function that I call from Swift, that takes a lot more parameters than shown here, among which is a reference to a Swift C typecast buffer to hold an error string. The compiler doesn't complain and the function call works. Hopefully this will steer you closer to the answer and you can provide an update with the final answer or someone else can.
var err = [CChar](count: 256, repeatedValue: 0)
var rv = somefunc((UnsafeMutablePointer<Int8>)(err))
if (rv < 0) {
println("Error \(err)")
return
}