मैं कुछ जीएनयू उपकरण, यानी जीएनयू सी ++ कंपाइलर (जी ++) और जीएनयू लिंकर (एलडी) का उपयोग कर एक साझा लाइब्रेरी (.so) फ़ाइल बनाने के लिए उपयोग कर रहा हूं एक बाइनरी निष्पादन योग्य फ़ाइल।जीएनयू लिंकर (एलडी) को एक प्रतीक निर्यात करने के लिए समस्या
द्विआधारी निष्पादन योग्य फ़ाइल रनटाइम पर साझा लाइब्रेरी फ़ाइल को गतिशील रूप से लोड करने के लिए dlopen
फ़ंक्शन का उपयोग करती है। इसके अतिरिक्त, साझा लाइब्रेरी फ़ाइल को एक विशेष श्रेणी विधि (ToolboxManager::registerToolbox
कहा जाता है) का आह्वान करने की आवश्यकता है जिसे बाइनरी निष्पादन योग्य के भीतर परिभाषित किया गया है। यह कक्षा विधि निर्यात करने के लिए बाइनरी निष्पादन योग्य को मजबूर कर समायोजित किया गया है, जो बदले में निम्नलिखित कमांड लाइन विकल्पों के साथ बाइनरी निष्पादन योग्य को लिंक करके लिंक समय पर पूरा किया जाता है;
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
जहां फ़ाइल ${top_srcdir}/dynamic_symbol_table.txt
में निम्न सामग्री शामिल है;
{
extern "C++"
{
"ToolboxManager::registerToolbox*";
};
};
नोट फ़ाइल में तारांकित (*) के उपयोग के सभी प्रतीकों कि ToolboxManager::registerToolbox
के साथ शुरू निर्यात करने के लिए लिंकर मजबूर करने के लिए।
जब मैं परिणामी बाइनरी निष्पादन योग्य पर जीएनयू एनएम उपयोगिता (nm -C -g ./a.out
) चलाता हूं, तो यह उपर्युक्त वर्ग विधि के बारे में निम्न जानकारी प्रदर्शित करता है;
08053da0 T ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
या, एनएम उपयोगिता के रूप में ऊपर लागू किया गया है, लेकिन -सी कमांड लाइन स्विच के उपयोग के बिना इस समय;
08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
अभी तक, यह ठीक दिखता है। कक्षा विधि ToolboxManager::registerToolbox
की परिभाषा के सामने "टी", यह दर्शाता है कि विधि फ़ाइल के टेक्स्ट/कोड अनुभाग में रहती है।
इसी प्रकार, यदि मैं साझा लाइब्रेरी फ़ाइल पर एनएम उपयोगिता (nm -C -g ./toolbox.so
) चलाता हूं, तो यह उसी उपर्युक्त वर्ग विधि के बारे में निम्न जानकारी प्रदर्शित करता है;
U ToolboxManager::registerToolbox
(
std::string&,
std::string&,
std::map
<
std::string,
Factory_DSPB_Base*,
std::less
<
std::string
>,
std::allocator
<
std::pair
<
std::string const,
Factory_DSPB_Base*
>
>
>&
)
यह भी ठीक दिखता है। कक्षा विधि ToolboxManager::registerToolbox
की परिभाषा के सामने "यू", इंगित करता है कि साझा लाइब्रेरी फ़ाइल में विधि अपरिभाषित है।
हालांकि, एक समस्या तब होती है जब मैं कमांड लाइन से बाइनरी एक्टेक्टेबल चलाता हूं और इस समस्या के परिणामस्वरूप निम्न त्रुटि संदेश प्रदर्शित होता है;
./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
इस रनटाइम संदेश में दिखाई देने वाली उलझन वाली क्लास विधि नाम नीचे दी गई है, जैसा कि दो पंक्तियों में से पहला है। तुलनात्मक उद्देश्यों के लिए, उपरोक्त से गुस्सा वर्ग विधि का नाम (और जिसे nm -g
कमांड का उपयोग करके उत्पन्न किया गया था) को दो पंक्तियों के दूसरे के रूप में नीचे दिखाया गया है;
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE
जैसा देखा जा सकता है, दो उलझन वाले नाम समान हैं। इसलिए, मैं समझ नहीं पा रहा हूं कि अपरिभाषित प्रतीक रनटाइम पर क्यों हल नहीं किया जा सकता है।
फिर मैंने बाइनरी निष्पादन योग्य को फिर से जोड़ा, हालांकि इस बार मैंने निम्नलिखित लिंकर कमांड को प्रतिस्थापित किया;
-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt
इस के साथ;
-Wl,--export-dynamic
--export-dynamic
लिंकर विकल्प जीएनयू लिंकर गतिशील प्रतीक मेज पर सभी प्रतीकों को जोड़ने के लिए निर्देश देता है।
यदि फिर बाइनरी निष्पादन योग्य फिर से चलाया गया। इस बार यह सही ढंग से निष्पादित किया गया था और dlopen फ़ंक्शन पर कॉल के परिणामस्वरूप एक अपरिभाषित प्रतीक त्रुटि नहीं हुई थी। यह मुझे पूरी तरह से परेशान करता है, क्योंकि ऐसा लगता है कि प्रतीक को बाइनरी निष्पादन योग्य के प्रारंभिक संस्करण में सही ढंग से निर्यात किया जा रहा है। क्या कोई यहां समस्या को देखने में सक्षम है? किसी भी सहायता की सराहना की जाएगी।
अग्रिम धन्यवाद।