2010-05-29 12 views
8

क्या यह जांचने का कोई तरीका है कि संकलित समय पर सी-लिंकेज (यानी extern "C" के साथ) दिया गया फ़ंक्शन घोषित किया गया है या नहीं?जांच कर रहा है कि किसी फ़ंक्शन में संकलन-समय पर सी-लिंकेज है [असफल]

मैं एक प्लगइन सिस्टम विकसित कर रहा हूं। प्रत्येक प्लगइन प्लगइन-लोडिंग कोड में फैक्ट्री फ़ंक्शंस की आपूर्ति कर सकता है। हालांकि, इसे नाम के माध्यम से किया जाना चाहिए (और GetProcAddress या dlsym के बाद के उपयोग)। इसके लिए यह आवश्यक है कि कार्यों को सी-लिंकेज के साथ घोषित किया जाए ताकि नाम-उलझन को रोका जा सके। यदि संदर्भित फ़ंक्शन को C++ - लिंकेज के साथ घोषित किया गया है (रनटाइम पर खोजने के विपरीत, उस नाम के साथ कोई फ़ंक्शन मौजूद नहीं है) तो एक कंपाइलर त्रुटि फेंकने में सक्षम होना अच्छा होगा।

यहाँ मैं क्या मतलब है की एक सरल उदाहरण है:

extern "C" void my_func() 
{ 
} 

void my_other_func() 
{ 
} 

// Replace this struct with one that actually works 
template<typename T> 
struct is_c_linkage 
{ 
    static const bool value = true; 
}; 

template<typename T> 
void assertCLinkage(T *func) 
{ 
    static_assert(is_c_linkage<T>::value, "Supplied function does not have C-linkage"); 
} 

int main() 
{ 
    assertCLinkage(my_func); // Should compile 
    assertCLinkage(my_other_func); // Should NOT compile 
} 

वहाँ is_c_linkage के संभावित कार्यान्वयन है कि दूसरी समारोह के लिए एक संकलक त्रुटि फेंक है, लेकिन पहले नहीं? मुझे यकीन नहीं है कि यह संभव है (हालांकि यह एक कंपाइलर एक्सटेंशन के रूप में मौजूद हो सकता है, जिसे मैं अभी भी जानना चाहता हूं)। धन्यवाद।

+6

मुझे दृढ़ता से संदेह है कि यह नहीं किया जा सकता - विशेष रूप से मानक तरीके से नहीं। दिलचस्प सवाल, यद्यपि। –

+2

मुझे इसके बारे में इतना यकीन नहीं है। लेकिन अगर यह किया जा सकता है, तो यह काफी संभावना है कि जीसीसी इसका समर्थन नहीं करेगा, क्योंकि यह बाहरी "सी" और बाहरी "सी ++" फ़ंक्शन प्रकार के भेद को नहीं जानता है। इस प्रकार यह दोनों प्रकार के समान व्यवहार करता है। –

+0

यदि आप कार्यान्वयन विशिष्ट ज्ञान के लिए जा रहे हैं तो आप इसे –

उत्तर

2

मैं जोनाथन लेफ्लर से सहमत हूं कि यह संभवतः एक मानक तरीके से संभव नहीं है। शायद यह कुछ हद तक संभव होगा, कंपाइलर और कंपाइलर के संस्करण के आधार पर, लेकिन आपको संभावित दृष्टिकोण निर्धारित करने के लिए प्रयोग करना होगा और इस तथ्य को स्वीकार करना होगा कि कंपाइलर का व्यवहार अनजाने में था और बाद के संस्करणों में "निश्चित" हो सकता है।

void my_func() __attribute__((stdcall)); 
void my_func() { } 

void my_other_func() { } 

template <typename ret_, typename... args_> 
struct stdcall_fun_t 
{ 
    typedef ret_ (*type)(args_...) __attribute__((stdcall)); 
}; 

int main() 
{ 
    stdcall_fun_t<void>::type pFn(&my_func), 
     pFn2(&my_other_func); 
} 

g++ -std=c++0x क्योंकि इस कोड को संकलित करने के लिए विफल रहता है:

g++ के साथ संस्करण 4.4.4 डेबियन निचोड़ पर, उदाहरण के लिए, आप कार्यों कि stdcall इस दृष्टिकोण के साथ नहीं कर रहे हैं के लिए एक संकलक त्रुटि को बढ़ाने के लिए सक्षम हो सकता है :

SO2936360.cpp:17: error: invalid conversion from ‘void ()()’ to ‘void ()()’

लाइन 17 pFn2 की घोषणा है। अगर मैं इस घोषणा से छुटकारा पाता हूं, तो संकलन सफल होता है।

दुर्भाग्यवश, यह तकनीक cdecl के साथ काम नहीं करती है।

0

यूनिक्स/लिनक्स के लिए, परिणामी बाइनरी का विश्लेषण 'एनएम' के साथ और प्रतीक नामों की तलाश के बारे में कैसे करें? मुझे लगता है कि यह आपके लिए क्या मतलब नहीं है, लेकिन फिर भी यह संकलन समय की तरह है।

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