2012-01-17 37 views
6

मैं जीएनयू के लिंकर रैप विकल्प की सहायता से टेम्पलेट फ़ंक्शन को लपेटने का प्रयास करता हूं। कोड इस तरह दिखता है:लपेटना सी ++ टेम्पलेट फ़ंक्शन

// f.h 
template<typename T> 
void f(T t) { 
} 

// bar.h 
void bar(); 

// bar.cpp 
#include "bar.h" 
#include "f.h" 

void bar() { 
    f(42); 
} 

// test.cpp 
extern "C" { 
    extern void __real__Z1fIiEvT_(int i); 
    void __wrap__Z1fIiEvT_(int i) { 
    __real__Z1fIiEvT_(i); 
    } 
} 

int main() { 
    bar(); 
} 

ऊपर दिखाए गए कोड निम्न आदेश के साथ जुड़ा हुआ है:

g++ -Xlinker -wrap=_Z1fIiEvT_ -o test test.o bar.o 

दुर्भाग्य से, यह काम नहीं करता है और हमेशा मूल कार्य के बजाय कहा जाता है मेरी लिपटे संस्करण __wrap__Z1fIiEvT_। क्या आप मेरी गलतियों को देखते हैं?

संपादित: http://linux.die.net/man/1/ld से

$ g++ -c bar.cpp -o bar.o 
$ nm bar.o 
0000000000000000 W _Z1fIiEvT_ 
+1

डबल चेक आप 'एनएम' या इसी तरह के टूल का उपयोग करके सही सजाए गए फ़ंक्शन को कॉल कर रहे हैं। उस से प्रासंगिक आउटपुट को प्रश्न में जोड़ना सहायक हो सकता है। – uesp

+0

एफ (42) नहीं होना चाहिए; एफ (42) हो? –

+1

@ फायर-ड्रैगन-डीओएल - टेम्पलेट फ़ंक्शंस तर्क से उनके तर्क प्रकारों का अनुमान लगाएंगे, और चूंकि int अन्यथा अवांछित पूर्णांक शाब्दिक प्रकार का प्रकार है, यह ठीक काम करता है। यदि एफ एक वर्ग था, तो टेम्पलेट तर्क स्पष्ट होना चाहिए। – Marc

उत्तर

1

: के रूप में की सलाह दी है, मैं एनएम यहाँ के उत्पादन में लगता है कि मैं कोई गलती टेम्पलेट समारोह के घायल नाम के साथ नहीं किया है बनाने के लिए संलग्न

--wrap = प्रतीक
प्रतीक के लिए एक रैपर फ़ंक्शन का उपयोग करें। प्रतीक के लिए कोई अपरिभाषित संदर्भ "_ रैप प्रतीक" के लिए हल किया जाएगा। "_ वास्तविक प्रतीक" के किसी भी अनिर्धारित संदर्भ को प्रतीक के लिए हल किया जाएगा।

मुझे लगता है कि "अपरिभाषित" शब्द यहां कुंजी हो सकता है। ब्याज का आपका प्रतीक निश्चित रूप से बार.ओ में परिभाषित किया गया है, और nm आउटपुट इसकी पुष्टि करता है, क्योंकि अपरिभाषित प्रतीकों को "यू" के साथ चिह्नित किया गया है, न कि "डब्ल्यू"।


अद्यतन:

मुझे लगता है कि यह इसलिए संभव टेम्पलेट कार्यों रैप करने के लिए नहीं है?

मुझे लगता है कि यह फ़ंक्शन परिभाषित (या तत्काल) कहां पर निर्भर करता है, और यदि यह परिभाषा लिंकर के लिए उपलब्ध है। आपके मामले में, यदि आपने bar.cpp में एक गैर-टेम्पलेट फ़ंक्शन को परिभाषित किया है, जहां इसका उपयोग किया जाता है, तो परिणाम वही होगा। भले ही आपने bar.cpp में फ़ंक्शन को परिभाषित किया हो लेकिन इसे main.cpp में उपयोग किया गया, मुझे लगता है कि यह वही होगा, हालांकि पूरी तरह से सुनिश्चित नहीं है (आप इसे आज़मा सकते हैं)। और मुझे यकीन है कि यदि आपने bar.cpp और main.cpp को विभिन्न मॉड्यूल (एक साझा लाइब्रेरी और निष्पादन योग्य) में लिंक किया है, तो आप main.cpp में उपयोग किए गए bar.cpp से फ़ंक्शन को लपेटने में सक्षम होंगे, फिर भी कोई फर्क नहीं पड़ता चाहे वह टेम्पलेट है या नहीं।


अद्यतन 2: मुझे यकीन है कि नहीं था, लेकिन माइक प्रयोग (अपने ही जवाब और वहाँ टिप्पणी देखें) कि रैपिंग काम करता है, तो प्रतीक एक वस्तु फ़ाइल में अपरिभाषित है, भले ही उस वस्तु फ़ाइल से जुड़ा हुआ है के साथ की पुष्टि एक और ऑब्जेक्ट फ़ाइल के साथ प्रतीक परिभाषा युक्त। महान!

+0

के लिए ठीक है धन्यवाद आप सही हैं। चूंकि संकलक तत्काल फ़ंक्शन टेम्पलेट के लिए कोड उत्पन्न करता है, यह अब एक अनिर्धारित प्रतीक नहीं है और इसलिए लिंकर इसे "_wrap_symbol" पर लपेट नहीं देगा। मुझे लगता है कि इसलिए टेम्पलेट कार्यों को लपेटना संभव नहीं है? – Mike

1

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

//bar.cpp 
#include "bar.h" 

template<typename T> void f(T); 

void bar() { 
f(42); 
} 

//f.h 
template<typename T> 
void f(T t) { 
} 

//f.cpp 
#include "f.h" 
template void f(int); 


$ nm bar.o 
       U _Z1fIiEvT_ 
0000000000000000 T _Z3barv 
+0

लेकिन, क्या यह अभी भी अपरिभाषित माना जाता है जब bar.o निष्पादन योग्य फ़ाइल बनाने के लिए f.o के साथ एक साथ जुड़ा हुआ है? मैं स्वीकार करता हूं कि मेरे पास यह सुनिश्चित करने के लिए '-वाप' के साथ व्यावहारिक अनुभव नहीं है कि यह क्या करेगा। –

+0

जाहिर है हां, अन्यथा लिंकर '_wrap' उपसर्ग के साथ प्रतीक को लपेट नहीं करेगा, या मैं गलत हूं? उपरोक्त दिया गया उदाहरण काम करता है जब इस पोस्ट की शुरुआत में कोड में दिखाए गए मैंगलेड लिपटे नाम ('_Z1fIiEvT_') के साथ उपयोग किया जाता है। – Mike

+0

फिर, ज़ाहिर है, हाँ। मैं अपना जवाब संशोधित करूंगा और आपकी जांच का संदर्भ दूंगा। धन्यवाद! –