正确使用Objective C ++

我为iOS编写了一个应用程序,最近我在一个Objective C实现(.m)文件中包含了一个C ++头文件。 我把扩展名从.m改为.mm,期望一切顺利运行。

意外的是我的C ++类的.h文件中有多个编译器错误。

如:“C ++需要所有声明的types说明符”和“重复成员…”。

有谁知道是什么原因造成的?

编辑 – 我已经添加了上下文的C ++头文件:

#ifndef __CAAudioUnitOutputCapturer_h__ #define __CAAudioUnitOutputCapturer_h__ #include <AudioToolbox/ExtendedAudioFile.h> /* Class to capture output from an AudioUnit for analysis. example: CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false); CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD); { captor.Start(); ... captor.Stop(); } // can repeat captor.Close(); // can be omitted; happens automatically from destructor */ class CAAudioUnitOutputCapturer { public: enum { noErr = 0 }; CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) : mFileOpen(false), mClientFormatSet(false), mAudioUnit(au), mExtAudioFile(NULL), mBusNumber (busNumber) { CFShow(outputFileURL); OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile); if (!err) mFileOpen = true; } void Start() { if (mFileOpen) { if (!mClientFormatSet) { AudioStreamBasicDescription clientFormat; UInt32 size = sizeof(clientFormat); AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size); ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat); mClientFormatSet = true; } ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL); // initialize async writes AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this); } } void Stop() { if (mFileOpen) AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this); } void Close() { if (mExtAudioFile) { ExtAudioFileDispose(mExtAudioFile); mExtAudioFile = NULL; } } ~CAAudioUnitOutputCapturer() { Close(); } private: static OSStatus RenderCallback( void * inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { if (*ioActionFlags & kAudioUnitRenderAction_PostRender) { CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon; static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8); if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) { OSStatus result = ExtAudioFileWriteAsync(This->mExtAudioFile, inNumberFrames, ioData); if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", (int)result); } } return noErr; } bool mFileOpen; bool mClientFormatSet; AudioUnit mAudioUnit; ExtAudioFileRef mExtAudioFile; UInt32 mBusNumber; }; #endif // __CAAudioUnitOutputCapturer_h__ 

不幸的是,如果你刚刚开始上课.mm ,那么任何使用.mm标题的类都将需要变成.mm 。 如果你继续只是改变你的类扩展,你最终会做出整个项目Objective-c ++。 如果这是你的意图,那么你可以改变你的构build设置来编译为Objective-C ++(这可能是一个痛苦的房子)。

但是,如果你使用一些标题魔法,你将避免很多麻烦。 只要确保在编译之前将您的Compile sources as更改Compile sources as build属性即可。

下面是我用我编写的一个封装类来从我的其他Objective-c类中分离出一个c ++类的东西。 c ++类是MyClass

MyClassWrapper.h

 //declare c++ impl for Obj-C++ #ifdef __cplusplus class CppPlanterModel; namespace com{namespace company{namespace mypackage {class MyClass;}}} typedef com::company::mypackage::MyClass CppMyClass; #endif //declare obj-c impl #ifdef __OBJC__ #ifndef __cplusplus typedef void CppMyClass; #endif #endif @interface MyClassWrapper : NSObject { CppMyClass* _myClass; } //etc etc @end 

MyClassWrapper.mm

 #include "MyClass.h" using namespace com:company:mypackage; class CppMyClass : public MyClass { CppMyClass() {}; ~CppMyClass() {}; //other stuff you might like to have }; @implementation MyClassWrapper //etc etc @end 

这是另外一件事我做了一个不同的头来处理共享extern东西:

Something.h

 #ifdef __cplusplus #define FV_EXTERN extern "C" __attribute__((visibility ("default"))) #else #define FV_EXTERN extern __attribute__((visibility ("default"))) #endif FV_EXTERN const int kMyInt; FV_EXTERN int GetAnotherInt(...); 

我build议阅读这个关于包装c ++(也可以链接到其他类似主题的博客条目)的博客条目: http : //robnapier.net/blog/wrapping-c-take-2-1-486

遵循Rob Napier博客的代码,我为CAAudioUnitOutputCapturer做了这个。 以为我会分享它,以节省其他人的时间。

RNWrap.h

 // // RNWrap.h // // ObjC wrapper for Wrap.cpp // #import <Foundation/Foundation.h> #import <CoreFoundation/CoreFoundation.h> #import <AudioUnit/AudioUnit.h> #import <AudioToolbox/AudioToolbox.h> #import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h> struct RNWrapOpaque; @interface RNWrap : NSObject { struct RNWrapOpaque *_cpp; } - (id) initWithAudioUnit:(AudioUnit) au andURL:(CFURLRef) outputFileURL andAudioFileTypeID:(AudioFileTypeID) fileType andAudioStreamBasicDescription: (const AudioStreamBasicDescription) asbd; - (void) Start; - (void) Close; - (void) Stop; @end 

RNWrap.mm

 // // RNWrap.mm // Objective C++ Wrapper Class for CAAudioUnitOutputCapturer.h // // Created by Pier 23/10/12 // Copyright 2012 DreamUpApps. All rights reserved. // #import "RNWrap.h" #import "CAAudioUnitOutputCapturer.h" @interface RNWrap () @property (nonatomic, readwrite, assign) RNWrapOpaque *cpp; @end @implementation RNWrap @synthesize cpp = _cpp; struct RNWrapOpaque { public: RNWrapOpaque(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription format) : outputCapturer(au, outputFileURL, fileType, format, 0) {}; // note added bus number = 0 at the end CAAudioUnitOutputCapturer outputCapturer; }; - (id)initWithAudioUnit:(AudioUnit) au andURL:(CFURLRef) outputFileURL andAudioFileTypeID:(AudioFileTypeID) fileType andAudioStreamBasicDescription: (const AudioStreamBasicDescription) format { self = [super init]; if (self != nil) { self.cpp = new RNWrapOpaque(au, outputFileURL, fileType, format); } return self; } - (void)dealloc { delete _cpp; _cpp = NULL; //[super dealloc]; } - (void) Start { self.cpp->outputCapturer.Start(); } - (void) Stop { self.cpp->outputCapturer.Stop(); } - (void) Close { self.cpp->outputCapturer.Close(); } @end 

你在class上这样使用它。

 - (void) captureInAppAudio:(AudioUnit) auToCapture { AudioStreamBasicDescription destFormat; memset( &destFormat, 0, sizeof(AudioStreamBasicDescription) ); destFormat.mSampleRate = 44100; destFormat.mFormatID = kAudioFormatLinearPCM; destFormat.mFormatFlags = ( kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagIsBigEndian ); destFormat.mBytesPerPacket = 2; destFormat.mFramesPerPacket = 1; destFormat.mBytesPerFrame = 2; destFormat.mChannelsPerFrame = 1; destFormat.mBitsPerChannel = 16; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; soundPath = [documentsDirectory stringByAppendingString:@"/recording.caf"] ; CFURLRef fileurl = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)soundPath, kCFURLPOSIXPathStyle, false); captor = [[RNWrap alloc] initWithAudioUnit:auToCapture andURL:fileurl andAudioFileTypeID:'caff' andAudioStreamBasicDescription:destFormat]; [captor Start]; } 

希望这可以帮助别人!

docker。