Вопрос по objective-c, ios, xcode – Правильно используйте Objective C ++

2

Я кодирую приложение для iOS и недавно # включил заголовочный файл C ++ в файл реализации Objective C (.m). Я изменил расширение с .m на .mm и ожидал, что все будет работать гладко.

Неожиданно я получил несколько ошибок компилятора в файле .h моего класса C ++.

Например: & quot; C ++ требует спецификатора типа для всех объявлений & quot; и & quot; Дублировать член ... & quot ;.

Кто-нибудь знает, что может быть причиной этого?

Редактировать - я добавил заголовочный файл C ++ для контекста:

<code>#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__
</code>
@pmjordan Я только что добавил нужный заголовочный файл. Может быть, это поможет. Orpheus Mercury
Есть конкретные примеры? Я предполагаю, что какой-то тип не был определен, или имеется конфликт имен с одним из типов времени выполнения Objective C. Но это проблема, я могу только догадываться. pmdj
Пожалуйста, дайте нам фактические сообщения об ошибках, которые вы получаете; никто не хочет охотиться через сотни строк кода, чтобы угадать, какой из них может быть неправильным! Это также помогло бы предоставить нам файл .mm (или, по крайней мере, показать нам, что еще вы включаете перед этим файлом .h). abarnert

Ваш Ответ

2   ответа
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

Вот еще одна вещь, которую я сделал с другим заголовком для управления совместным использованием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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Orpheus Mercury
Error: User Rate Limit Exceeded Orpheus Mercury
Error: User Rate Limit Exceeded.mmError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Orpheus Mercury
3

следуя коду в блоге Роба Напира, я сделал это для 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];
}

Надеюсь, что это поможет кому-то еще там!

Пирс.

Похожие вопросы