正确使用Objective C ++ [英] Properly use Objective C++

查看:145
本文介绍了正确使用Objective C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为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 ++的博客文章(其中还包含指向其他博客条目的链接)主题): http://robnapier.net/blog/wrapping-c-拿2-1-486

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 ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆