2011-08-05 17 views
8

मैं आसपास googled से एक उद्देश्य सी समारोह कॉलिंग और मैं एक मिलियन परिणाम इस विषय लगता है। लेकिन कोई भी पेज मेरी मदद नहीं करता है। मुझे लगता है कि मुझे एक बहुत ही आम समस्या है। मैं ऑडियो प्रोग्रामिंग के साथ खेल रहा हूं विशेष रूप से ऑडियो कतारों के साथ काम कर रहा हूं। मेरे कार्यक्रम का उद्देश्य समस्या को समझाने के लिए कोई फर्क नहीं पड़ता। लेकिन संक्षेप में: जब मैं C++ कोड से ऑब्जेक्ट-सी फ़ंक्शन को कॉल करने का प्रयास करता हूं तो मुझे एक त्रुटि मिलती है। AudioRecorder.h: तो यहाँ मेरी कोड है कि त्रुटि है हैसी ++ कोड

#import <Foundation/Foundation.h> 


@interface AudioRecorder : NSObject { 

} 

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

@end 

और यह दिया गया है: AudioRecorder.mm:

#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...."); 
} 

जब मैं छोड़ "[आत्म playAlarmSound]," तो सब कुछ ठीक काम करता है। तो मैं अपने उद्देश्य + सी कोड से इस उद्देश्य-सी फ़ंक्शन को कैसे कॉल करूं?

उत्तर

6

self केवल उद्देश्य-सी विधियों में मौजूद है और यह एक सी शैली का कार्य है। आप एक ऑब्जेक्टिव-सी विधि से inUserData को self पारित करने के लिए जब आप कॉलबैक की स्थापना की है, तो यह सही प्रकार पर वापस डाली की जरूरत है।

//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 
); 

और अपने मूल कार्यान्वयन

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]; 
    ... 
} 
+0

@mbehan आप सही :) – Joe

+1

यह सच थे, लेकिन मैं बहस चाहते हैं कि अंतर्निहित कारण 'स्वयं' याद आ रही है, क्योंकि इस का एक तरीका नहीं है वर्ग, नहीं क्योंकि यह एक सी-शैली समारोह है। किसी भी ऑब्जेक्टिव-सी वस्तु इस समारोह के भीतर प्रयोग करने योग्य है - यह सिर्फ इतना है कि 'स्वयं' एक वर्ग के तरीकों में ही उपलब्ध है। – Luke

+0

मुझे विश्वास है कि है कि मैं क्या कहा गया है "आत्म केवल ऑब्जेक्टिव-सी तरीकों में मौजूद है और है कि एक सी शैली समारोह है" लिखने में कोई त्रुटि मूल रूप से किया था, जहां यह कहा एक लेकिन यह है कि एक ही संदेश देने चाहिए। – Joe

4

यह वास्तव में एक आम समस्या है। self यहाँ काम नहीं करता है क्योंकि इस AudioRecorder वर्ग का एक तरीका नहीं है, इसलिए नहीं कि यह ऑब्जेक्टिव-सी कोड है। आप एक उद्देश्य-सी ++ फ़ाइल में हैं, इसलिए सभी मान्य उद्देश्य-सी कोड काम करेंगे। [anAudioRecorder playAlarmSound] ठीक काम करेगा, बशर्ते आपके पास anAudioRecorder का अच्छा संदर्भ हो।

तो कैसे हम अगर हम self लिए पहुँच नहीं है एक संदर्भ मिलता है? हमेशा की तरह अपने AudioRecorder वस्तु के सूचक के रूप में इस समारोह का void* aqData तर्क का उपयोग करने के लिए है। जब आप इस कॉलबैक पंजीकृत है, आप इसे इस मामले में एक सूचक अपने AQRecorderState वस्तु या struct, जो तुम वैसे भी उपयोग करने के लिए नहीं लग रहे करने के लिए कहा, क्या void* तर्क होगा। इसके बजाय आप पंजीकरण करते समय self पर पॉइंटर का उपयोग कर सकते हैं ताकि आप उस ऑब्जेक्ट का उपयोग यहां कर सकें।

एक अन्य विकल्प के लिए एक साझा AudioRecorder वस्तु है, जो मामले में आप AudioRecorder वस्तु आप चाहते हैं पाने के लिए [AudioRecorder sharedInstance] की तरह कुछ (एक वर्ग है, नहीं एक उदाहरण, विधि) कहेंगे उपयोग करने के लिए किया जाएगा। क्योंकि अन्य जवाब यहाँ पहली विधि पर बताते हैं, तो यहां आपको साझा उदाहरण विकल्प का उपयोग करने के लिए: फिर

static AudioRecorder* sharedMyInstance = nil; 

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

, जब आप इस तरह अपने AudioRecorder वस्तु को AudioRecorder की एक स्थिर उदाहरण और एक वर्ग विधि sharedInstance जोड़े, अपने कॉलबैक से AudioRecorder उपयोग करना चाहते हैं, तो आप [AudioRecorder sharedInstance] का उपयोग करके साझा उदाहरण मिल सकती है। यह एक बहुत उपयोगी प्रतिमान है यदि केवल AudioRecorder होने वाला है - यह बहुत से संदर्भ पास को समाप्त करता है।