Calling a Objective C function from C++ Code

て烟熏妆下的殇ゞ 提交于 2019-12-03 12:49:16

self only exists in Objective-C methods and that is a C style function. You need to pass self from an Objective-C method to the inUserData when you set up the callback, then cast it back to the correct type.

//This is an example for using AudioQueueNewInput
//Call this in an Objective-C method passing self to inUserData
AudioQueueNewInput (
   const AudioStreamBasicDescription  *inFormat,
   AudioQueueInputCallback            inCallbackProc,

   // this is where you will pass (void*)self
   void                               *inUserData, 
   CFRunLoopRef                       inCallbackRunLoop,
   CFStringRef                        inCallbackRunLoopMode,
   UInt32                             inFlags,
   AudioQueueRef                      *outAQ
);

And your original implementation

static void HandleInputBuffer (void                                 *aqData,
                           AudioQueueRef                        inAQ,
                           AudioQueueBufferRef                  inBuffer,
                           const AudioTimeStamp                 *inStartTime,
                           UInt32                               inNumPackets,
                           const AudioStreamPacketDescription   *inPacketDesc ) 
{
    AudioRecorder *ar_instance = (AudioRecorder*)aqData;
    ...
    [ar_instance playAlarmSound];
    ...
}

This is indeed a common problem. self doesn't work here because this is not a method of the AudioRecorder class, not because it's Objective-C code. You're in an Objective-C++ file, so all valid Objective-C code will work. [anAudioRecorder playAlarmSound] will work fine, provided you have a good reference to anAudioRecorder.

So how do we get a reference if we don't have access to self? The usual way is to use the void* aqData argument of this function as a pointer to your AudioRecorder object. When you registered this callback, you told it what the void* argument would be, in this case a pointer to your AQRecorderState object or struct, which you don't seem to use anyway. Instead you can use a pointer to self when you register so that you can use that object here.

Another option would be to use a shared AudioRecorder object, in which case you would call something like [AudioRecorder sharedInstance] (a class, not an instance, method) to get the AudioRecorder object you want. Because the other answer here elaborates on the first method, here's how to use the shared instance option: Add a static instance of AudioRecorder and a class method sharedInstance to your AudioRecorder object, like this:

static AudioRecorder* sharedMyInstance = nil;

+ (id) sharedInstance {
    @synchronized(self) {
        if( sharedMyInstance == nil )
            sharedMyInstance = [[super allocWithZone:NULL] init];
    }
    return sharedMyInstance;
} // end sharedInstance()

Then, when you want to use the AudioRecorder from your callback, you can get the shared instance using [AudioRecorder sharedInstance]. This is a very useful paradigm if there's only going to be one AudioRecorder - it eliminates a lot of reference passing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!