2013-05-31 8 views
6

मुझे मैक ओएस एक्स में रनटाइम पर लाइब्रेरी फ़ंक्शन से गतिशील रूप से लिंक करने की आवश्यकता है। Apple's example के बाद, मैं एक फ़ंक्शन पॉइंटर घोषित करता हूं और इसे dlsym() के परिणाम के साथ असाइन करता हूं। निम्न उदाहरण एक सादा सी (.c) फ़ाइल के रूप में सफलतापूर्वक संकलित करता है। लेकिन मैं एक सी ++ फ़ाइल में इस की जरूरत है, और अगर मैं एक सी ++ फ़ाइल (सीपीपी) के रूप में इस उदाहरण संकलन, बजना संकलक मुझसे कहता हैफ़ंक्शन पॉइंटर असाइनमेंट सी में काम करता है लेकिन सी ++

प्रकार का एक चर प्रारंभ नहीं कर सकता 'शून्य () (चार *)' प्रकार के एक राव्यू के साथ 'शून्य '

यह सादे 'सी' में क्यों काम करता है, और मैं इसे कैसे ठीक कर सकता हूं?

#include <dlfcn.h> 

void Test() { 
    // Load the library which defines myFunc 
    void* lib_handle = dlopen("myLib.dylib", RTLD_LOCAL|RTLD_LAZY); 

    // The following line is an error if compiled as C++ 
    void (*myFunc)(char*) = dlsym(lib_handle, "myFunc"); 

    myFunc("Hello"); 

    dlclose(lib_handle) ; 
} 

उत्तर

7

dlsym रिटर्न void*। पॉज़िक्स में (लेकिन मानक सी नहीं, जैसा कि जेम्स इंगित करता है) void* से पॉइंटर-टू-फ़ंक्शन प्रकार में एक निहित रूपांतरण है, इसलिए myFunc पर असाइनमेंट बस काम करता है। (या आप एक reinterpret_cast साथ फैंसी प्राप्त कर सकते हैं)

void (*myFunc)(char*) = (void(*)(char*))dlsym(lib_handle, "myFunc"); 

: C++ में कोई अंतर्निहित रूपांतरण (क्योंकि यह सुरक्षित टाइप नहीं है), तो आप संकलक कि तुम सच में एक डाली जोड़कर इसका मतलब यह बताने की आवश्यकता है।

+0

... या शायद 'static_cast': http://stackoverflow.com/questions/310451/should-i-use-static-cast-or-reinterpret-cast-when-casting-a-void-to- जो भी –

+2

सी मानक I का संस्करण कहता है कि 'शून्य' के लिए एक सूचक को किसी सूचक से या _object_ प्रकार '(जोर जोड़ा गया) में परिवर्तित किया जा सकता है। एक फ़ंक्शन ऑब्जेक्ट प्रकार नहीं है, और सी ने कभी भी 'शून्य *' और पॉइंटर्स के बीच रूपांतरणों (स्पष्ट या निहित) को रूपांतरणों की अनुमति नहीं दी है। मुझे यकीन नहीं है, लेकिन मुझे लगता है कि एक निदान की आवश्यकता है। (मुझे नहीं लगता कि यह अपरिभाषित व्यवहार है।) और स्पष्ट कलाकार (यहां तक ​​कि 'reinterpret_cast') भी काम नहीं करना चाहिए। (अधिकांश यूनिक्स कंपाइलर्स इस संबंध में अनुरूप नहीं हैं, लेकिन चूंकि यह एक एक्सटेंशन है, इसलिए प्रत्येक कंपाइलर इसे पसंद करने के लिए स्वतंत्र है।) –

+0

@ जेम्ससांज सही है, सी के पास 'शून्य *' से कोई संकेतक नहीं है, किसी भी पॉइंटर-टू- कार्य प्रकार एक अनुरूप सी संकलक को निदान जारी करना चाहिए (जो केवल एक चेतावनी हो सकता है); एक गैर-अनुरूप सी संकलक, जैसा कि अधिकांश डिफ़ॉल्ट रूप से होते हैं, वह कुछ भी पसंद कर सकते हैं। –

0

क्योंकि सी संकलक टूट गया है। (स्पष्ट या निहित) void* और फ़ंक्शन के लिए कोई संकेत नहीं है, न तो सी में और न ही C++ में।

void (*myFunc)(char *); 
*(void (**myFunc)(char*))(&myFunc) = dlsym(...); 

काम करेगा:

Posix कि सेल्सियस के लिए एक प्रतिबंध जोड़ता है, और की आवश्यकता है कि void* और कार्यों के लिए संकेत दिए गए एक ही आकार और प्रतिनिधित्व है, तो ।

सी ++ में, आप की तरह कुछ का उपयोग करना चाहें:

class GetFunctionHelper; 
GetFunctionHelper getFunction(void* dlHandle, std::string const& functionName); 

class GetFunctionHelper 
{ 
    void* fromSystem; 
    freind GetFunctionHelper getFunction(void* , std::string const&); 
    GetFunctionHelper(void* fromSystem) : fromSystem(fromSystem) {} 
public: 
    template <typename Ptr> operator Ptr() const 
    { 
     return *reinterpret_cast<Ptr const*>(&fromSystem); 
    } 
}; 

GetFunctionHelper 
getFunction(void* dlHandle, std::string const& functionName) 
{ 
    return GetFunctionHelper(dlsym(dlHandle, functionName.c_str())); 
} 

(ज़ाहिर है, थोड़ा और त्रुटि जाँच के साथ)।

+0

'शून्य *' से एक पॉइंटर-टू-फ़ंक्शन प्रकार तक एक स्पष्ट रूपांतरण (यानी, एक कास्ट), जहां तक ​​मैं कह सकता हूं, किसी भी बाधा का उल्लंघन नहीं करता है। लेकिन चूंकि मानक इस तरह के रूपांतरण के व्यवहार को परिभाषित नहीं करता है, इसलिए इसका व्यवहार अपरिभाषित है। POSIX शायद व्यवहार को परिभाषित करता है, क्योंकि यह करने के लिए स्वतंत्र है। –

+0

धन्यवाद, @ जेम्स। मैं संकलक की कमी पर टिप्पणी करने के लिए पर्याप्त स्मार्ट नहीं हूँ। इसके अलावा, आपकी दूसरी पंक्ति संकलित नहीं है। टाइपो 'यू' बनाम 'वाई' के अलावा, स्पष्ट रूप से एक सही कोष्ठक भी गायब है, लेकिन मुझे पता नहीं चल सकता कि कहां जाना चाहिए। –

+0

@ किथ थॉम्पसन मैं सी के बारे में निश्चित नहीं हूं; सी ++ में, एक निदान की आवश्यकता होती है। हाल ही में, पॉक्सिक्स ने मूल रूप से उपरोक्त मेरे पहले उदाहरण का उपयोग करने के लिए कहा; जब मैंने इसे इस बार देखा, हालांकि, उन्होंने एक कंपाइलर एक्सटेंशन का उपयोग करने के लिए कहा। तो मुझे नहीं पता (सी के संबंध में)। प्रैक्टिस में, मैंने हमेशा अपने सी ++ संस्करण की तरह कुछ उपयोग किया है, इसलिए समस्या कभी नहीं उभरी (भी, मैंने वास्तव में यूनिक्स कंपाइलर को कभी नहीं देखा है जो इस नियम को लागू करता है)। –

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