2011-02-15 13 views
8

से फ्रीग्ल में कॉलबैक फ़ंक्शन मैं ओपनजीएल का उपयोग करने के लिए एमएसवीसी ++ और फ्रीग्लूट का उपयोग कर रहा हूं। अब, मेरे पास Camera नामक एक वर्ग है, जो कि बहुत आसान है, लेकिन यह मेरी खिड़की के पुनः आकार के लिए भी कार्य करता है।ऑब्जेक्ट

मेरा प्रश्न है: मैं अपने कैमरे में अपने फ़ंक्शन में glutReshapeFunc(void (*callback)(int,int)) कैसे सेट कर सकता हूं?

मैं निम्नलिखित कोड है, जो काम नहीं करेगा, एक संकलक त्रुटि के कारण:

int main(int argc, char **argv) 
{ 
    Camera *camera = new Camera(); 
    glutReshapeFunc(camera->ReshapeCamera); 
} 

और मेरे कैमरा वर्ग में इस तरह दिखता है Camera.h:

class Camera 
{ 
public: 
    Camera(void); 
    ~Camera(void); 
    void ReshapeCamera(int width, int height); 
}; 

हो सकता है कि यह सिर्फ एक सामान्य कॉलबैक प्रश्न है, लेकिन इंटरनेट पर मिली एकमात्र चीज़ कॉलबैक के आस-पास कुछ रैपर वर्ग बना रही थी। लेकिन ऐसा नहीं लगता है कि यह इतना कठिन होना चाहिए। अग्रिम धन्यवाद।

उत्तर

10

ऐसा करने का कोई साफ तरीका नहीं है। सी वस्तुओं के बारे में नहीं जानता है, इसलिए पॉइंटर्स-टू-सदस्य काम नहीं करते हैं। सी टेम्पलेट्स नहीं करता है, इसलिए मज़ेदार काम नहीं करते हैं। एपीआई आपको अपने कॉलबैक में मनमाने ढंग से void *userData पास करने की अनुमति नहीं देती है, इसलिए आप ऑब्जेक्ट को इस तरह से पास नहीं कर सकते हैं।

तो, वास्तव में, आपको एक रैपर फ़ंक्शन बनाना होगा जो एक सदस्य फ़ंक्शन नहीं है, और आपको किसी स्थिर और/या वैश्विक चर के माध्यम से इसे किसी भी तरह Camera ऑब्जेक्ट इंस्टेंस तक पहुंच देना होगा।

यदि इस घटना के लिए कई ऑब्जेक्ट्स सुन रहे हैं, तो आप एक सिंगलटन क्लास बना सकते हैं जो आपको मनमानी श्रोताओं को पंजीकृत करने की अनुमति देता है।

2

आप इसे सीधे कनेक्ट नहीं कर सकते हैं। ReshapeCamera एक सदस्य समारोह है, इसे चलाने के लिए कैमरे के उदाहरण की आवश्यकता है। ग्लूट कॉलबैक एक सी फ़ंक्शन है, जिसमें आपकी विधि को कॉल करने के लिए कैमरा का उदाहरण नहीं है। आपको एक ऐसा फ़ंक्शन बनाना होगा जो कैमरा रीशेप विधि को कॉल करे।

1

इसका "सी बनाम सी ++" चीज़ से कोई लेना देना नहीं है। आपको बस यह समझने की आवश्यकता है कि सदस्य फ़ंक्शन कॉल क्या होता है और मूल रूप से यह किस प्रकार संकलित होता है।

myObject.memberFunction(); // This is what the programmer sees. 
memberFunction(&myObject); // This is what the compiler sees. 

एक सदस्य फ़ंक्शन एक फ़ंक्शन का एक फैंसी विवरण है जो ऑब्जेक्ट को पहले पैरामीटर के रूप में ले जाता है। यह वास्तविक पैरामीटर सूची में केवल अदृश्य है।

void MyClass::memberFunction() // This is the declaration the programmer sees. 
void memberFunction(MyClass* this) // This is what the compiler sees. 

वहां से, सी ++ ऑब्जेक्ट उन्मुख फैशन में काम करना आसान बनाने के लिए विशेष अर्थशास्त्र जोड़ता है। इसलिए, भले ही आपके ऑब्जेक्ट में फॉर्मेट शून्य (int, int) का सदस्य फ़ंक्शन है, लेकिन वास्तव में प्रारूप शून्य (कैमरा *, int, int) है, और यह वांछित प्रारूप से मेल नहीं खाता है! यही कारण है कि स्थिर फ़ंक्शन सदस्य ऐसे फ़ंक्शन पॉइंटर्स के लिए उपयोग किए जा सकते हैं। कभी ध्यान दें कि स्थिर सदस्य कार्य "इस" के सदस्यों तक नहीं पहुंच सकते हैं? ऐसा इसलिए है क्योंकि स्थिर सदस्य कार्य "इस" का प्रतिनिधित्व करने वाले ऑब्जेक्ट का एक उदाहरण पास करते हैं।

असल में, आप सादे सी में ऑब्जेक्ट उन्मुख प्रोग्रामिंग का अनुकरण कर सकते हैं। यदि आप पहले पैरामीटर के रूप में स्ट्रक्चर पॉइंटर लेते हुए फ़ंक्शंस का एक सेट बनाते हैं, तो आपको कई फायदे मिलते हैं!

+0

इसलिए मैंने अब अपनी कक्षा में एक स्थिर कार्य बनाया है, लेकिन ऐसा लगता है कि यह __thiscall से __decl में परिवर्तित नहीं हो सकता है। 'त्रुटि 1 त्रुटि C2664:' glutReshapeFunc ':' void (__thiscall कैमरा :: *) (int, int) 'से' void (__cdecl *) (int, int) 'पैरामीटर 1 को परिवर्तित नहीं कर सकता है। और एक स्पष्ट __cdecl जोड़कर 'कैमरा ::' -part के बारे में चेतावनी देता है। – Marnix

+0

@ मार्निक्स: '__thiscall' मुझे बताता है कि 'glutReshapeFunc' को' स्थिर 'के रूप में घोषित नहीं किया गया है। – Thomas

+0

@ थॉमस: कोई glutReshapeFunc शायद सी में एक फ़ंक्शन है, मेरे कैमरा वर्ग से आने वाला फ़ंक्शन स्थिर है, लेकिन इसलिए एक और नामस्थान है। तो ऐसा नहीं लगता है। – Marnix

0

निम्नलिखित दर्शाता है कि सी ++ से सी कॉलबैक फ़ंक्शन को कैसे पंजीकृत किया जाए, यह आमतौर पर उपयोगी है, जो ग्लूट के लिए विशिष्ट नहीं है।

यहाँ अपने ग्राहक C++ कार्यक्रम

int main(int argc, char *argv[]) { 

std::cout << "launching Camera ..." << std::endl; 

Camera * camera = new Camera(); 

// ------ glut new window boilerplate ------- // 

int WindowHandle = 0; 
glutInit(&argc, argv); 
WindowHandle = glutCreateWindow("hello there"); 
if(WindowHandle < 1) { 
    std::cerr << "ERROR: Could not create a new rendering window" << std::endl; 
    exit(EXIT_FAILURE); 
} 
// ------------------------------------------ // 

camera->setup_callback(); 

glutMainLoop(); 

return 0; 

}

यहाँ है Camera.cpp

Camera * ptr_global_instance = NULL; 

extern "C" void ReshapeCamera_callback(int width, int height) { 
    // c function call which calls your c++ class method 
    ptr_global_instance->ReshapeCamera_cb(width, height); 
} 

void Camera::ReshapeCamera_cb(int width, int height) { 
    std::cout << "width " << width << " height " << height << std::endl; 
} 

void Camera::setup_callback() { 
    // c++ method which registers c function callback 
    ::ptr_global_instance = this; 
    ::glutReshapeFunc(::ReshapeCamera_callback); 
} 

और उसके शीर्ष लेख Camera.h

class Camera { 
public: 
    void ReshapeCamera_cb(int width, int height); 
    void setup_callback(); 
}; 

सूचना है का उपयोग एक सी ++ ग्लोबल क्लास पॉइंटर ptr_global_instance

संबंधित मुद्दे