C++ 从C++;代码

C++ 从C++;代码,c++,objective-c,call,C++,Objective C,Call,我在谷歌上搜索了一下,找到了一百万个关于这个主题的结果。但是没有一页对我有帮助。我想我有一个非常普遍的问题。我正在玩音频编程,尤其是处理音频队列。我的程序的目的与解释问题无关。但简单来说,当我尝试从C++代码调用Objto-C函数时,会出错。下面是我的代码,其中包含错误: 录音机.h: #import <Foundation/Foundation.h> @interface AudioRecorder : NSObject { } -(void)setup; -(void)s

我在谷歌上搜索了一下,找到了一百万个关于这个主题的结果。但是没有一页对我有帮助。我想我有一个非常普遍的问题。我正在玩音频编程,尤其是处理音频队列。我的程序的目的与解释问题无关。但简单来说,当我尝试从C++代码调用Objto-C函数时,会出错。下面是我的代码,其中包含错误: 录音机.h:

#import <Foundation/Foundation.h>


@interface AudioRecorder : NSObject {

}

-(void)setup;
-(void)startRecording;
-(void)endRecording;
-(void)playAlarmSound;

@end
#导入
@接口录音机:NSObject{
}
-(无效)设置;
-(无效)开始记录;
-(无效)终止记录;
-(无效)播放警报声;
@结束
这是实现: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....");
}
#导入“AudioRecorder.h”
#包括
#包括
使用名称空间std;
@录音机的实现
静态常数int kNumberBuffers=3;
...
静态void HandleInputBuffer(void*aqData,
音频队列参考inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp*inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription*inPacketDesc){
AQRecorderState*pAqData=(AQRecorderState*)aqData;
如果(inNumPackets==0&&
pAqData->mDataFormat.mBytesPerPacket!=0)
inNumPackets=
在buffer->mAudioDataByteSize/pAqData->mDataFormat.mBytesPerPacket;
UInt32尺寸;
AudioQueueGetPropertySize(inAQ、kAudioQueueProperty_CurrentLevelMeter和size);
char*levelMeterData=新字符[大小];
AudioQueueGetProperty(inAQ、kAudioQueueProperty_CurrentLevelMeter、levelMeterData和size);
AudioQueueLevelMeterState*meterState=重新解释强制转换(levelMeterData);

cout这确实是一个常见问题。
self
在这里不起作用,因为这不是
AudioRecorder
类的方法,也不是因为它是Objective-C代码。您在Objective-C++文件中,所以所有有效的Objective-C代码都可以工作。
[anAudioRecorder playAlarmSound]
如果您对音频录像机有一个很好的参考,它将很好地工作

那么,如果我们不能访问
self
,我们如何获得引用呢?通常的方法是使用此函数的
void*aqData
参数作为指向
AudioRecorder
对象的指针。当您注册此回调时,您告诉它
void*
参数是什么,在本例中是指向
AQRe的指针corderState
对象或结构,您似乎无论如何都不会使用它。相反,您可以在注册时使用指向
self
的指针,以便在此处使用该对象

另一种选择是使用共享的
录音机
对象,在这种情况下,您可以调用类似
[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 sharedInstance]获取共享实例
。如果只有一个
录音机,这是一个非常有用的范例,它消除了大量的引用传递。

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”缺失的根本原因是因为它不是类的方法,不是因为它是C风格的函数。任何Objective-C对象都可以在这个函数中使用——只是“self”只在类的方法中可用。我相信这就是我所说的“self只存在于Objective-C方法中,这是一个C风格的函数”最初有一个拼写错误,上面写着一个,但应该传达相同的信息。