2008-11-11 12 views
21

को बढ़ावा देना चाहते हैं :: एक सादा फ़ंक्शन पॉइंटर (समान हस्ताक्षर) की अपेक्षा करने वाली विधि से बाध्य करें।डेमोटे बूस्ट :: एक सादा फ़ंक्शन पॉइंटर

typedef void TriggerProc_type(Variable*,void*); 
void InitVariable(TriggerProc_type *proc); 
boost::function<void (Variable*, void*)> triggerProc ... 
InitVariable(triggerProc); 

error C2664: 'InitVariable' : cannot convert parameter 1 from 
'boost::function<Signature>' to 'void (__cdecl *)(type *,void *)' 

मैं एक बढ़ावा भंडारण से बच सकते हैं :: समारोह और बस सीधे बाध्य functor गुजरती हैं, लेकिन फिर मैं मिल समान त्रुटि:

error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter 
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)' 

उत्तर

39

किसी को भी देखा गया है कि accepted answer केवल तुच्छ मामलों के साथ काम करता है देखते हैं? <> :: लक्ष्य() कार्य करने का एकमात्र तरीका एक ऑब्जेक्ट लौटाएगा जो सी कॉलबैक से बंधे जा सकते हैं, अगर यह किसी ऑब्जेक्ट के साथ बनाया गया था जो सी कॉलबैक से बंधे जा सकते हैं। यदि ऐसा है, तो आप इसे सीधे बाध्य कर सकते हैं और सभी फ़ंक्शन <> बकवास से शुरू कर सकते हैं।

यदि आप इसके बारे में सोचते हैं, तो इसके लिए कोई जादू समाधान नहीं है। एक सी-स्टाइल कॉलबैक को एक पॉइंटर के रूप में संग्रहीत किया जाता है जो निष्पादन योग्य कोड को इंगित करता है। कोई भी नॉनट्रिविअल बूस्ट :: फ़ंक्शन <> कम से कम दो पॉइंटर्स की आवश्यकता होगी: निष्पादन योग्य कोड में से एक, दूसरे को उस कॉल को सेट करने के लिए आवश्यक डेटा (जैसे 'यह' पॉइंटर, बाध्य सदस्य के मामले में समारोह)।

बूस्ट :: फ़ंक्शन और बूस्ट :: सी कॉलबैक के साथ बाध्य करने का सही तरीका एक शिम फ़ंक्शन बनाना है जो कॉलबैक हस्ताक्षर को संतुष्ट करता है, जो आंकड़े <> कॉल करने के लिए कहता है, और इसे कॉल करता है। आमतौर पर सी कॉलबैक में 'उपयोगकर्ता डेटा' के लिए कुछ प्रकार का शून्य होगा; कि जहां आप अपने समारोह सूचक भी छिपा सकते है:

typedef void (*CallbackType)(int x, void* user_data); 
void RegisterCallback(CallbackType cb, void* user_data); 

void MyCallback(int x, void* userData) { 
    boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData); 
    pfn(x); 
} 

boost::function<void(int)> fn = boost::bind(myFunction(5)); 
RegisterCallback(MyCallback, &fn); 
बेशक

, यदि आपका कॉलबैक हस्ताक्षर उपयोगकर्ता डेटा सूचक किसी तरह शामिल नहीं है, तो आप भाग्य से बाहर रहे हैं। लेकिन किसी भी कॉलबैक जिसमें उपयोगकर्ता डेटा पॉइंटर शामिल नहीं है, ज्यादातर वास्तविक दुनिया परिदृश्यों में पहले से ही अनुपयोगी है, और इसे फिर से लिखना होगा।

+1

'boost :: function pfn = static_cast > (userData); 'बूस्ट :: फंक्शन * का उपयोग करना चाहिए या इसके बजाय संकलन त्रुटि होगी? – Gohan

+0

@ गोहन हां, वह लेखक का इरादा था। मैं पोस्ट को ठीक कर दूंगा .. – Yann

11

मुझे लगता है कि आप लक्ष्य का उपयोग करना चाहते() सदस्य समारोह बूस्ट :: फ़ंक्शन (यह एक मुंह नहीं है ...)

#include <boost/function.hpp> 
#include <iostream> 

int f(int x) 
{ 
    return x + x; 
} 

typedef int (*pointer_to_func)(int); 

int 
main() 
{ 
    boost::function<int(int x)> g(f); 

    if(*g.target<pointer_to_func>() == f) { 
    std::cout << "g contains f" << std::endl; 
    } else { 
    std::cout << "g does not contain f" << std::endl; 
    } 

    return 0; 
} 
0

क्या आप इसे बांधने के साथ काम कर सकते हैं?

#include <boost/function.hpp> 
#include <boost/bind.hpp> 

void f(int x) 
{ 
    (void) x; 
    _asm int 3; 
} 

typedef void (*cb_t)(int); 

int main() 
{ 
    boost::function<void (int x)> g = boost::bind(f, 3); 
    cb_t cb = *g.target<cb_t>(); //target returns null 
    cb(1); 

    return 0; 
} 

अद्यतन: ठीक है, अच्छी तरह से इरादा एक कार्य-कॉलबैक में एक विधि को बांधना है। तो अब क्या?

+0

इसे बिना बाध्य किए कॉलबैक में डेटा प्राप्त करने का एकमात्र तरीका, एक मुक्त ऑब्जेक्ट –

3

can you get it working with bind?

cb_t cb = *g.target<cb_t>(); //target returns null 

यह by design है। असल में, चूंकि bind एक पूरी तरह से अलग प्रकार देता है, ऐसा कोई तरीका नहीं है कि यह काम करेगा। असल में, एक बाइंडर प्रॉक्सी ऑब्जेक्ट को सी फ़ंक्शन पॉइंटर में परिवर्तित नहीं किया जा सकता है (क्योंकि यह एक नहीं है: यह फ़ंक्शन ऑब्जेक्ट है)। boost::bind द्वारा लौटाया गया प्रकार जटिल है। वर्तमान सी ++ मानक आप जो चाहते हैं उसे करने का कोई अच्छा तरीका नहीं देता है। C++ 0x एक decltype अभिव्यक्ति जो यहां इस्तेमाल किया जा सकता कुछ इस तरह प्राप्त करने के साथ लगाया जाएगा:

typedef decltype(bind(f, 3)) bind_t; 
bind_t target = *g.target<bind_t>(); 

सूचना है कि इस या काम नहीं कर सकते हो सकता है। मेरे पास इसका परीक्षण करने का कोई तरीका नहीं है।

+0

के माध्यम से ठीक है, ठीक है, एक कार्य फ़ंक्शन-कॉलबैक में एक विधि को बांधना है। तो अब क्या? –

+0

असल में, आप नहीं कर सकते। 'बूस्ट :: बाइंड' और 'बूस्ट :: फंक्शन' का उपयोग नहीं कर रहा है।एकमात्र उपाय आवश्यक फ़ंक्शन को हार्ड-कोड करना और उस पर एक पॉइंटर पुनर्प्राप्त करना हो सकता है। –

+6

मैन, यह पाइथन में 10 एस ले लिया होगा :( –

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