问题描述
我正在为iOS编写应用程序,最近我在Objective C实现(.m)文件中包含了一个C ++头文件。我将扩展名从.m更改为.mm并期望一切顺利运行。
I'm coding an app for iOS and I recently #included a C++ header file in an Objective C implementation (.m) file. I changed the extension from .m to .mm and expected everything to run smoothly.
出乎意料的是,我的C ++类的.h文件中出现了多个编译错误。
Unexpectedly I got multiple compiler errors in the .h file of my C++ class.
例如: C ++需要所有声明的类型说明符和重复成员......。
Such as: "C++ requires a type specifier for all declarations" and "Duplicate member...".
有谁知道是什么原因造成的?
Does anyone know what could be causing this?
编辑 - 我为上下文添加了C ++头文件:
Edit - I've added the C++ header file for context:
#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 ++。如果这是你的意图,那么你可以改变你的构建设置来编译Objective-c ++(这可能是你的痛苦之处)。
Unfortunately, if you just start making classes .mm
, any class that uses that .mm
's header will also need to become .mm
. If you continue to just change your class extensions, you will eventually make the whole project Objective-c++. If that is your intention, then you can just change your build settings to compile for Objective-c++ (which could be a house of pain for you).
但是,如果你使用一些标题魔法,你会避免很多麻烦。只需确保在编译之前将编译源编译为
build属性为根据文件类型
。
However, if you use some header magic, you will avoid a lot of hassle. Just make sure to change your Compile sources as
build property to According to file type
before compiling.
这是我用包装类做的事情,我写的是将c ++类与其余的Objective-c类隔离开来。 c ++类是 MyClass
。
Here's something I did with a wrapper class I wrote to isolate a c++ class from the rest of my Objective-c classes. The c++ class is 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
的东西:
Here's another thing I did with a different header to handle sharing extern
stuff:
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(...);
我建议阅读这篇关于包装c ++的博客文章(其中还包含指向其他博客条目的链接)主题):
I recommend reading this blog entry about wrapping c++ (which also has links to other blog entries of a similar topic): http://robnapier.net/blog/wrapping-c-take-2-1-486
这篇关于正确使用Objective C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!