2011-08-05 19 views
8

Çevreye baktım ve bu konuyla ilgili bir milyon sonuç buluyorum. Ama sayfaların hiçbiri bana yardım etmiyor. Bence çok yaygın bir sorunum var. Özellikle ses kuyrukları ile çalışan ses programlama ile uğraşıyorum. Programımın amacı problemi açıklamak için önemli değil. Ama kısaca: C++ kodundan bir objektif-c işlevini çağırmaya çalıştığımda bir hata alıyorum. AudioRecorder.h: Yani burada hata içeriyor benim kodudurC++ Code'dan bir Objective C işlevinin çağrılması

#import <Foundation/Foundation.h> 


@interface AudioRecorder : NSObject { 

} 

-(void)setup; 
-(void)startRecording; 
-(void)endRecording; 
-(void)playAlarmSound; 

@end 

Ve bu uygulamasıdır: AudioRecorder.mm: Ben ihmal

#import "AudioRecorder.h" 
#include <AudioToolbox/AudioToolbox.h> 
#include <iostream> 

using namespace std; 

@implementation AudioRecorder 

static const int kNumberBuffers = 3; 
... 
static void HandleInputBuffer (void         *aqData, 
          AudioQueueRef      inAQ, 
          AudioQueueBufferRef     inBuffer, 
          const AudioTimeStamp     *inStartTime, 
          UInt32        inNumPackets, 
          const AudioStreamPacketDescription *inPacketDesc) { 

    AQRecorderState *pAqData = (AQRecorderState *) aqData;    

    if (inNumPackets == 0 &&            
     pAqData->mDataFormat.mBytesPerPacket != 0) 
     inNumPackets = 
     inBuffer->mAudioDataByteSize/pAqData->mDataFormat.mBytesPerPacket; 

    UInt32 size; 
    AudioQueueGetPropertySize (inAQ, kAudioQueueProperty_CurrentLevelMeter, &size); 
    char* levelMeterData = new char[size]; 
    AudioQueueGetProperty (inAQ, kAudioQueueProperty_CurrentLevelMeter, levelMeterData, &size); 
    AudioQueueLevelMeterState* meterState = reinterpret_cast<AudioQueueLevelMeterState*>(levelMeterData); 
    cout << "mAveragePower = " << meterState->mAveragePower << endl; 
    cout << "mPeakPower = " << meterState->mPeakPower << endl; 
    delete levelMeterData; 
    [self playAlarmSound]; //<--- here I get the error: Use of undeclared identifier 'self' 

    if (pAqData->mIsRunning == 0)         
     return; 

    AudioQueueEnqueueBuffer (pAqData->mQueue, inBuffer, 0, NULL); 
} 
... 
-(void)playAlarmSound { 
    NSLog(@"Alarmsound...."); 
} 

"[öz playAlarmSound];" o zaman her şey iyi çalışıyor. Peki bu Objective-C işlevini C++ kodumdan nasıl ararım?

cevap

6

. Geri çağrıyı kurduğunuzda, self nesnesini bir Objective-C yönteminden inUserData'ya geçirmeniz ve sonra doğru türe geri göndermeniz gerekir.

//This is an example for using AudioQueueNewInput 
//Call this in an Objective-C method passing self to inUserData 
AudioQueueNewInput (
    const AudioStreamBasicDescription *inFormat, 
    AudioQueueInputCallback   inCallbackProc, 

    // this is where you will pass (void*)self 
    void        *inUserData, 
    CFRunLoopRef      inCallbackRunLoop, 
    CFStringRef      inCallbackRunLoopMode, 
    UInt32        inFlags, 
    AudioQueueRef      *outAQ 
); 

Ve orijinal uygulama

Doğru :)
+0

sınıf, C tarzı bir işlev olduğu için değil. Herhangi bir Objective-C nesnesi bu fonksiyon içerisinde kullanılabilir - sadece 'self' sadece bir sınıfın metotlarında kullanılabilir. – Joe

+1

Doğru, ama bu bir yöntem değildir çünkü altta yatan nedeni 'self' eksik olduğunu iddia ediyorum @mbehan

static void HandleInputBuffer (void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc) { AudioRecorder *ar_instance = (AudioRecorder*)aqData; ... [ar_instance playAlarmSound]; ... } 
Luke

+0

"Ben sadece Objective-C yöntemlerinde var olan ve bir C stili işlevi olan" bir başlangıçta bir yazım hatası yazdığını ancak aynı mesajı iletmesi gerektiğini belirttim. – Joe

4

Bu gerçekten yaygın bir sorundur. self burada çalışmıyor çünkü bu, Object-C kodu olduğundan değil, AudioRecorder sınıfının bir yöntemi değil. Bir Objective-C++ dosyasındasınız, dolayısıyla tüm geçerli Objective-C kodları çalışacaktır. anAudioRecorder için iyi bir başvuru olması koşuluyla [anAudioRecorder playAlarmSound] iyi çalışır.

self'a erişimimiz yoksa, nasıl bir başvuru alırız? Her zamanki yol, bu işlevin void* aqData argümanını AudioRecorder nesnesine bir işaretçi olarak kullanmaktır. Bu geri bildirimi kaydettiğinizde, void* argümanının ne olacağını, bu durumda AQRecorderState nesnesinin veya yapınızın bir göstergesini belirtmişsinizdir. Bunun yerine, bu nesneyi burada kullanabilmek için kayıt olduğunuzda self işaretçisini kullanabilirsiniz.

Başka bir seçenek istediğiniz AudioRecorder nesneyi almak için [AudioRecorder sharedInstance] gibi bir şey (bir sınıf değil, bir örnek, yöntem) çağırır ve bu durumda paylaşılan AudioRecorder nesne kullanmak olacaktır. Diğer cevap burada birinci yönteme detaylandıran Çünkü burada paylaşılan örnek seçeneğini kullanmak için: Bu gibi, AudioRecorder nesneye AudioRecorder statik örneği ve bir sınıf yöntemi sharedInstance ekleyin:

static AudioRecorder* sharedMyInstance = nil; 

+ (id) sharedInstance { 
    @synchronized(self) { 
     if(sharedMyInstance == nil) 
      sharedMyInstance = [[super allocWithZone:NULL] init]; 
    } 
    return sharedMyInstance; 
} // end sharedInstance() 

Sonra sizi AudioRecorder numaralı telefonu kullanmak istediğinizde, [AudioRecorder sharedInstance] kullanarak paylaşılan örneği alabilirsiniz. Bu sadece bir AudioRecorder olacaksa çok yararlı bir paradigmadır - çok fazla referans geçişini ortadan kaldırır. Nesne-C yöntemlerinde yalnızca var olan ve C stili işlevi olan