2

iOS 用のアプリをコーディングしていますが、最近、Objective C 実装 (.m) ファイルに C++ ヘッダー ファイルを #include しました。拡張子を .m から .mm に変更し、すべてがスムーズに実行されることを期待しました。

予期せず、C++ クラスの .h ファイルで複数のコンパイラ エラーが発生しました。

「C++ では、すべての宣言に型指定子が必要です」や「メンバーが重複しています...」など。

誰がこれを引き起こしているのか知っていますか?

編集 - コンテキスト用の 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__
4

2 に答える 2

3

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

クラスではこのように使用します。

- (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];
}

これが他の誰かに役立つことを願っています!

橋脚。

于 2012-10-25T08:20:52.657 に答える
2

残念ながら、クラスの作成を開始したばかりの場合は.mm、そのヘッダーを使用するクラス.mmも。になる必要があり.mmます。クラス拡張子を変更し続けると、最終的にプロジェクト全体がObjective-c++になります。それがあなたの意図であるなら、Objective-c ++用にコンパイルするようにビルド設定を変更することができます(これはあなたにとって苦痛の家かもしれません)。

ただし、ヘッダーマジックを使用すると、多くの手間を省くことができます。コンパイルする前に、Compile sources asビルドプロパティをに変更してください。According to file type

これは、c++クラスを残りのObjective-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

共有を処理するために別のヘッダーを使用して行ったもう1つのことは次の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(...);

c ++のラッピングに関するこのブログエントリ(同様のトピックの他のブログエントリへのリンクもあります)を読むことをお勧めします:http://robnapier.net/blog/wrapping-c-take-2-1-486

于 2012-05-10T18:36:05.793 に答える