[英]Calling a Objective C function from C++ Code
我搜索了一下,我發現這個主題有一百萬個結果。 但這些頁面都沒有幫助我。 我認為我有一個非常普遍的問題。 我正在玩音頻編程,特別是使用音頻隊列。 我的程序的目的與解釋問題無關。 但簡而言之:當我嘗試從c ++代碼調用objective-c函數時出現錯誤。 所以這是包含錯誤的代碼:AudioRecorder.h:
#import <Foundation/Foundation.h>
@interface AudioRecorder : NSObject {
}
-(void)setup;
-(void)startRecording;
-(void)endRecording;
-(void)playAlarmSound;
@end
這是實現:AudioRecorder.mm:
#import "AudioRecorder.h"
#include <AudioToolbox/AudioToolbox.h>
#include <iostream>
using namespace std;
@implementation AudioRecorder
static const int kNumberBuffers = 3;
...
static void HandleInputBuffer (void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc ) {
AQRecorderState *pAqData = (AQRecorderState *) aqData;
if (inNumPackets == 0 &&
pAqData->mDataFormat.mBytesPerPacket != 0)
inNumPackets =
inBuffer->mAudioDataByteSize / pAqData->mDataFormat.mBytesPerPacket;
UInt32 size;
AudioQueueGetPropertySize ( inAQ, kAudioQueueProperty_CurrentLevelMeter, &size );
char* levelMeterData = new char[size];
AudioQueueGetProperty ( inAQ, kAudioQueueProperty_CurrentLevelMeter, levelMeterData, &size );
AudioQueueLevelMeterState* meterState = reinterpret_cast<AudioQueueLevelMeterState*>(levelMeterData);
cout << "mAveragePower = " << meterState->mAveragePower << endl;
cout << "mPeakPower = " << meterState->mPeakPower << endl;
delete levelMeterData;
[self playAlarmSound]; //<--- here I get the error: Use of undeclared identifier 'self'
if (pAqData->mIsRunning == 0)
return;
AudioQueueEnqueueBuffer ( pAqData->mQueue, inBuffer, 0, NULL );
}
...
-(void)playAlarmSound {
NSLog(@"Alarmsound....");
}
當我省略“[self playAlarmSound];” 一切正常。 那么如何從我的C ++代碼中調用這個Objective-C函數呢?
self
僅存在於Objective-C方法中,並且是C樣式函數。 設置回調時,需要將self
從Objective-C方法傳遞給inUserData,然后將其強制轉換回正確的類型。
//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
);
和你原來的實施
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];
...
}
這確實是一個普遍的問題。 self
在這里不起作用,因為這不是AudioRecorder
類的方法,不是因為它是Objective-C代碼。 您使用的是Objective-C ++文件,因此所有有效的Objective-C代碼都可以使用。 [anAudioRecorder playAlarmSound]
可以正常工作,前提是您對anAudioRecorder
有很好的引用。
那么如果我們無法訪問self
我們如何獲得參考? 通常的方法是使用此函數的void* aqData
參數作為指向AudioRecorder
對象的指針。 當您注冊此回調時,您告訴它void*
參數是什么,在這種情況下是指向您的AQRecorderState
對象或結構的指針,您似乎無論如何都不會使用它。 相反,您可以在注冊時使用指向self
的指針,以便您可以在此處使用該對象。
另一種選擇是使用共享的AudioRecorder
對象,在這種情況下,您可以調用[AudioRecorder sharedInstance]
(類,而不是實例,方法)來獲取所需的AudioRecorder
對象。 因為這里的另一個答案詳細闡述了第一種方法,下面是如何使用共享實例選項:將AudioRecorder
的靜態實例和類方法sharedInstance
到AudioRecorder
對象,如下所示:
static AudioRecorder* sharedMyInstance = nil;
+ (id) sharedInstance {
@synchronized(self) {
if( sharedMyInstance == nil )
sharedMyInstance = [[super allocWithZone:NULL] init];
}
return sharedMyInstance;
} // end sharedInstance()
然后,當您想要從回調中使用AudioRecorder
,可以使用[AudioRecorder sharedInstance]
獲取共享實例。 如果只有一個AudioRecorder
這是一個非常有用的范例 - 它消除了大量的引用傳遞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.