2009-01-13 20 views
5

सबसे पहले मुझे यह मानना ​​है कि मेरे प्रोग्रामिंग कौशल बहुत सीमित हैं और मैंने एक (वास्तव में छोटा) मौजूदा सी ++ ओओपी प्रोजेक्ट लिया है जहां मैं अपनी सामग्री को धक्का देने की कोशिश करता हूं। दुर्भाग्य से मैं ' मुझे एक समस्या का सामना करना पड़ रहा है जो मेरे ज्ञान से परे है और मुझे यहां कुछ मदद मिलनी है। मैं कैमरे से छवियों को पकड़ने के लिए एक थर्ड पार्टी लाइब्रेरी (जिसे बदला नहीं जा सकता) के साथ काम कर रहा हूं और यहां कुछ प्लेसहोल्डर नामों का उपयोग करेगा।वर्ग सदस्य कार्य समस्याओं के लिए फ़ंक्शन पॉइंटर

तृतीय पक्ष लाइब्रेरी में एक सतत लाइव हड़पने शुरू करने के लिए "थर्डपार्टी ग्रेब" एक फ़ंक्शन है और एक फ़ंक्शन में पॉइंटर लेता है जिसे प्रत्येक बार एक नया फ्रेम आने पर बुलाया जाएगा। तो एक सामान्य सी आवेदन में यह इस प्रकार है:

ThirdPartyGrab (HookFunction); 

"HookFunction" की जरूरत घोषित करने के रूप में:

long _stdcall HookFunction (long, long, void*); 

या "BUF_HOOK_FUNCTION_PTR" जो

typedef long (_stdcall *HOOK_FUNCTION_PTR) (long, long, void*); 

के रूप में घोषित किया जाता है अब मेरे पास एक सी ++ एप्लिकेशन है और एक वर्ग "MyFrameGrabber" है जो मुझे जो कुछ भी करता है उसे समाहित करना चाहिए।

long _stdcall HookFunction (long, long, void*); 

इसके अलावा मेरी कक्षा में एक सार्वजनिक शून्य समारोह "StartGrab" जो ले लो शुरू कर देना चाहिए है: तो मैं इस तरह एक निजी सदस्य के रूप में हुक समारोह में डाल दिया। अंदर मैं कॉल करने का प्रयास करता हूं:

ThirdPartyGrab (..., HookFunction, ...); 

जो (आश्चर्य की बात नहीं) विफल रहता है। ऐसा नहीं है कि समारोह कॉल MyFrameGrabber को :: HookFunction तर्क सूची याद करते हैं और मैं & MyFrameGrabber :: HookFunction का उपयोग करने के बजाय एक सूचक बनाने के लिए प्रयास करना चाहिए कहते हैं। हालांकि गुजर "& MyFrameGrabber :: HookFunction" के बजाय एक और त्रुटि में परिणाम है कि इस BUF_HOOK_FUNCTION_PTR में परिवर्तित नहीं किया जा सकता है।

C++ FAQ function pointers के माध्यम से पढ़ने के बाद मुझे लगता है कि मैं समस्या को समझता हूं लेकिन समाधान नहीं बना सकता। मैंने हुक फ़ंक्शन को स्थिर बनाने की कोशिश की लेकिन यह भी एक रूपांतरण त्रुटि में परिणाम। मैंने वर्ग के बाहर हुक फ़ंक्शन डालने का भी विचार किया लेकिन मुझे हुक फ़ंक्शन के अंदर कक्षा फ़ंक्शंस का उपयोग करने की आवश्यकता है। क्या कोई और तरीका है या मुझे अपनी पूरी अवधारणा को बदलने की ज़रूरत है?

संपादित 14.01.08: मैं सिंगलटन वैकल्पिक हल का परीक्षण के बाद से मैं तीसरे पक्ष के पुस्तकालय को बदल नहीं सकते और शून्य सूचक केवल डेटा है कि हुक समारोह के अंदर प्रयोग किया जाता है के लिए है। दुर्भाग्य से यह बॉक्स से बाहर काम किया नहीं था जैसे मैं आशा व्यक्त की .... स्थिर समारोह तो मैं इसे अपने "MyFrameGrabber" वर्ग में डाल एक अलग वर्ग में होने की जरूरत है, तो मैं नहीं जानता कि:

static MyFrameGrabber& instance() 
{ 
     static MyFrameGrabber _instance; 
     return _instance; 
} 
long Hook(long, long, void*); // Implementation is in a separate cpp file 

मेरी cpp फ़ाइल में मैं call_hook समारोह है:

long MFTYPE call_hook(long x, MIL_ID y, void MPTYPE *z) 
{ 
    return MyFrameGrabber::instance().Hook(x,y,z); 
} 
void 
MyFrameGrabber::grab() 
{ 
    ThirdPartyGrab(..., call_hook, ...); 
} 

लेकिन यह मुझे उस से मेल खाते कोई मानक निर्माता पाया जाता है static MatroxFrameGrabber _instance; में एक त्रुटि देता है।

MyFrameGrabber (void* x, 
       const std::string &y, int z, 
       std::string &zz); 

मैं एक खाली निर्माता MyFrameGrabber(); में डालने की कोशिश की, लेकिन यह एक लिंकर त्रुटि में परिणाम है: क्योंकि मेरे MyFrameGrabber निर्माता इस तरह दिखता है यह सही है। क्या मुझे सिंगलटन में MyFrameGrabber कन्स्ट्रक्टर को खाली पैरामीटर पास करना चाहिए? या क्या मुझे एक अलग हुक क्लास की आवश्यकता है और यदि हां, तो मैं MyFrameGrabber फ़ंक्शंस को कैसे एक्सेस कर सकता हूं? अग्रिम में धन्यवाद।

दूसरा संस्करण 15.01.08: मैंने परिवर्तनों को लागू किया और यह अब संकलित और लिंक करता है। दुर्भाग्य से मैं इसे रनटाइम पर अभी भी परीक्षण नहीं कर सकता क्योंकि यह एक डीएलएल है और मेरे पास अभी तक कोई डीबग कॉलर एक्स नहीं है और प्रारंभिकरण आदि के दौरान अन्य समस्याएं हैं। मैं पोस्ट को उत्तर के रूप में चिह्नित करूंगा क्योंकि मुझे यकीन है कि यह करने का यह सही तरीका है।

उत्तर

2

कारण "& MyFrameGrabber :: HookFunction" एक BUF_HOOK_FUNCTION_PTR में परिवर्तित नहीं किया जा सकता है कि, वर्ग के एक सदस्य होने के नाते, यह पहले पैरामीटर के रूप परोक्ष है "इस" सूचक है, इस प्रकार आप एक सदस्य समारोह एक को परिवर्तित नहीं कर सकते गैर-सदस्य कार्य: दो हस्ताक्षर समान दिखते हैं लेकिन वास्तव में अलग हैं।

मैं एक इंटरफ़ेस घोषित करता हूं, कॉल करने के लिए फ़ंक्शन को परिभाषित करता हूं, अपनी कक्षा को कार्यान्वित करता हूं और कॉलबैक के बजाय ऑब्जेक्ट को पास करता हूं (आप फ़ंक्शन पॉइंटर के ऑब्जेक्ट-उन्मुख प्रतिस्थापन के रूप में इंटरफ़ेस के बारे में सोच सकते हैं):

class IHookInterface{ 
public: 
    virtual long HookFunction(long, long, void*) = 0; 
}; 
class HookClass : public IHookInterface{ 
public: 
    virtual long Hook(long, long, void*) { 
     // your code here... 
    } 
}; 

// नई परिभाषा: थर्डपार्टी ग्रेब (..., IHookInterface, ...);

संपादित करें - अन्य संभव समाधान मामले में आप पुस्तकालय को संशोधित नहीं कर सकते हैं: एक स्थिर समारोह के बजाय एक सिंगलटन का उपयोग करें।

class HookClass{ 
public: 
    static HookClass& instance(){ 
     static HookClass _instance; 
     return _instance; 
    } 
    long Hook(long, long, void*) { 
     // your code here... 
    } 
}; 

long call_hook(long x,long y,void * z){ 
    return HookClass::instance().Hook(x,y,z); 
} 

दूसरा संपादित करें: यदि आप थोड़ा उचित मानकों के साथ निर्माता कॉल करने के लिए एक विधि के साथ प्रारंभ सिंगलटन वर्ग को संशोधित सकता है, लेकिन शायद यह निम्नलिखित समाधान है, जो सरल है की तुलना में अधिक सुंदर नहीं है:

class HookClass{ 
public: 

    HookClass(string x,string y...){ 
    } 

    long Hook(long, long, void*) { 
     // your code here... 
    } 
}; 

static HookClass * hook_instance = 0; 

long call_hook(long x,long y,void * z){ 
    if (0 != hook_instance){ 
     return hook_instance->Hook(x,y,z); 
    } 
} 

int main(){ 
    hook_instance = new HookClass("x","y"); 
    ThirdPartyGrab(..., call_hook, ...); 
} 
+0

मुझे लगता है कि "थर्ड-पार्टी लाइब्रेरी" के साथ ओपी का मतलब है कि वह लाइब्रेरी को नहीं बदल सकता है। हालांकि, मेरी धारणा गलत हो सकती है। – gimpf

+0

@gimpf - धन्यवाद, आप शायद सही हैं ... –

+0

सी कॉलबैक में शून्य * पैरामीटर का एक सामान्य उपयोग यह है-> सी ++ के लिए पॉइंटर। इसका मतलब है कि आप लंबे (हुक, हुक) लिखेंगे और स्थिर हुक_इंस्टेंस छोड़ देंगे – MSalters

7

आपकी निजी सदस्य विधि में पहले तर्क के रूप में this पॉइंटर का निहित है। यदि आप इसे लिखते हैं, तो यह स्पष्ट है कि फ़ंक्शन हस्ताक्षर मेल नहीं खाते हैं।

आप एक स्थिर सदस्य समारोह है, जो पुस्तकालय के लिए कॉलबैक-समारोह के रूप में पारित किया जा सकता लिखने के लिए की जरूरत है। ।

 
class MyClass { 
    long MyCallback(long, long) { 
    // implement your callback code here 
    } 

    static long __stdcall ThirdPartyGrabCallback(long a, long b, void* self) { 
    return reinterpret_cast<MyClass*>(self)->MyCallback(a, b); 
    } 
public: 
    void StartGrab() { 
    ThirdPartyGrab(..., &MyClass::ThirdPartyGrabCallback, ..., this, ...); 
    } 
}; 
: HookFunction को अंतिम तर्क, एक void*, सभी में एक कुकी है, जहां एक में लोगों को खुद सूचक पारित कर सकते हैं की तरह बहुत ज्यादा मेरे लिए लग रहा है

तो, सब, यह कुछ इस तरह होना चाहिए

यह निश्चित रूप से केवल तभी काम करता है जब void* तर्क मैंने जो कहा है वह कर रहा है। ThirdPartyGrab() कॉल में this की स्थिति को उपलब्ध पैरामीटर नामों सहित पूर्ण फ़ंक्शन हस्ताक्षर होने पर कॉल करना आसान होना चाहिए।

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