Translate to Objective-C from Objective-C++
-
09-10-2019 - |
Question
I have this code in a .mm
void MyMIDINotifyProc(const MIDINotification *message, void *refCon);
which goes with this line
MIDIClientCreate((CFStringRef)@"MidiMonitor MIDI Client", MyMIDINotifyProc, self, &client);
and then the MyMIDINotifyProc gets called from CoreMIDI.
Without changing the file extension to .m, I translated to an Obj-C signature:
@interface MidiInput (Private)
-(void) MyMIDINotifyProc:(const MIDINotification *)message reference:(void *)refCon;
@end
which compiles, but then I have no idea what to do with the MIDIClientCreate
line. As is, it produces "MyMIDINotifyProc" was not declared in this scope
. It's supposed to be of type void *
... And the docs are 100% clear that it's A refCon passed back to notifyRefCon
(link).
Is this problem solvable in Obj-C alone? I imagine I'd have to translate the C++ stuff to C, in which case I would just leave it alone.
Solution
MIDIClientCreate
expects an ordinary C function as its callback. You can't pass it an Objective-C method because the calling convention is different (in C terms, the first two parameters to an Objective-C method are self
and _cmd
- the selector - which will not be there for an ordinary C function).
The usual way around this is to create a C function that acts as a shim and explicitly pass self as a parameter. The shim function then immediately sends the objective-C message. I'm not familiar with this library, but it looks like refCon
is a parameter designed for exactly this sort of thing. So in your .m
file you need a function like this.
static void MyMIDINotifyProc(const MIDINotification *message, void *refCon)
{
[(id) refCon MIDINotify: message];
}
You also need a method to do the actual stuff:
-(void) MIDINotify: (const MIDINotification*) message
{
// do stuff
}
And you call MIDIClientCreate exactly as you were doing originally.