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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top