यदि मेरे पास दो पुस्तकालय हैं जो समान नामों के साथ कार्य प्रदान करते हैं तो मुझे क्या करना चाहिए?
vorbis_...
, sf_...
, sdl_...
)। यह अनिवार्य रूप से नामांकित कार्यों के प्रतीक नामों के लिए C ++ क्या करता है।
यदि मेरे पास दो पुस्तकालय हैं जो समान नामों के साथ कार्य प्रदान करते हैं तो मुझे क्या करना चाहिए?
vorbis_...
, sf_...
, sdl_...
)। यह अनिवार्य रूप से नामांकित कार्यों के प्रतीक नामों के लिए C ++ क्या करता है।
जवाबों:
Apropos टिप्पणियाँ: "निर्यात" से मेरा मतलब है कि लाइब्रेरी से जुड़ने वाले मॉड्यूल को दृश्यमान बनाना --- extern
फ़ाइल स्कोप पर कीवर्ड के बराबर । यह कैसे नियंत्रित किया जाता है यह ओएस और लिंकर पर निर्भर है। और यह कुछ ऐसा है जिसे मुझे हमेशा देखना है।
किसी ऑब्जेक्ट फ़ाइल का उपयोग करके प्रतीकों का नाम बदलना संभव है objcopy --redefine-sym old=new file
(देखें आदमी objcopy)।
फिर बस अपने नए नामों का उपयोग करके फ़ंक्शन को कॉल करें और नई ऑब्जेक्ट फ़ाइल के साथ लिंक करें।
विंडोज के तहत, आप उन लाइब्रेरियों में से एक को मेमोरी में लोड करने के लिए LoadLibrary () का उपयोग कर सकते हैं और फिर एक फ़ंक्शन पॉइंटर के माध्यम से फ़ंक्शन को कॉल करने और कॉल करने के लिए आवश्यक प्रत्येक फ़ंक्शन का पता प्राप्त करने के लिए GetProcAddress () का उपयोग करें।
जैसे
HMODULE lib = LoadLibrary("foo.dll");
void *p = GetProcAddress(lib, "bar");
// cast p to the approriate function pointer type (fp) and call it
(*fp)(arg1, arg2...);
FreeLibrary(lib);
foo.dll में बार नामक फ़ंक्शन का पता मिलेगा और उसे कॉल करें।
मुझे पता है कि यूनिक्स सिस्टम समान कार्यक्षमता का समर्थन करते हैं, लेकिन मैं उनके नामों के बारे में नहीं सोच सकता।
dlopen
dlsym
, और dlclose
। हालाँकि, यूनिक्स पर एनकैप्सुलेशन विंडोज पर उतना प्रभावी नहीं हो सकता है।
यहाँ एक विचार है। एक हेक्स संपादक में आपत्तिजनक पुस्तकालयों में से एक को खोलें और आपत्तिजनक तारों के सभी घटनाओं को कुछ और में बदल दें। फिर आपको भविष्य के सभी कॉल में नए नामों का उपयोग करने में सक्षम होना चाहिए।
अद्यतन: मैंने अभी इसे इस छोर पर किया है और यह काम करने लगता है। बेशक, मैंने इसे पूरी तरह से जांचा-परखा नहीं है - यह आपके पैरों को हेक्सिडिट शॉटगन से उड़ाने के लिए वास्तव में अच्छा तरीका नहीं हो सकता है।
यह मानते हुए कि आप लिनक्स का उपयोग करते हैं, जिसे आपको सबसे पहले जोड़ना होगा
#include <dlfcn.h>
उचित संदर्भ में फ़ंक्शन पॉइंटर चर की घोषणा करें, उदाहरण के लिए,
int (*alternative_server_init)(int, char **, char **);
जैसा कि फेरुस्कोयो ने https://stackoverflow.com/a/678453/1635364 में कहा है , स्पष्ट रूप से उस लाइब्रेरी को लोड करें जिसे आप निष्पादित करना चाहते हैं (अपने पसंदीदा झंडे उठाएं)
void* dlhandle;
void* sym;
dlhandle = dlopen("/home/jdoe/src/libwhatnot.so.10", RTLD_NOW|RTLD_LOCAL);
उस फ़ंक्शन का पता पढ़ें जिसे आप बाद में कॉल करना चाहते हैं
sym = dlsym(dlhandle, "conflicting_server_init");
निम्नानुसार असाइन करें और कास्ट करें
alternative_server_init = (int (*)(int, char**, char**))sym;
मूल की तरह ही कॉल करें। अंत में, निष्पादित करके अनलोड करें
dlclose(dlhandle);
आपको उन्हें एक साथ उपयोग नहीं करना चाहिए। अगर मुझे सही से याद है, तो लिंकर ऐसे मामले में त्रुटि जारी करता है।
मैंने कोशिश नहीं की, लेकिन एक समाधान के साथ हो सकता है dlopen()
, dlsym()
और dlclose()
जो आपको प्रोग्राम को गतिशील पुस्तकालयों को संभालने की अनुमति देता है। यदि आपको एक ही समय में दो कार्यों की आवश्यकता नहीं है, तो आप पहली लाइब्रेरी खोल सकते हैं, पहले फ़ंक्शन का उपयोग कर सकते हैं और दूसरी लाइब्रेरी / फ़ंक्शन का उपयोग करने से पहले पहली लाइब्रेरी को बंद कर सकते हैं।
अगर आपके पास .o फाइलें हैं, तो यहां एक अच्छा जवाब है: https://stackoverflow.com/a/6940389/4707057
सारांश:
objcopy --prefix-symbols=pre_string test.o
.o फ़ाइल में प्रतीकों का नाम बदलने के लिए या
objcopy --redefine-sym old_str=new_str test.o
.o फ़ाइल में विशिष्ट प्रतीक का नाम बदलने के लिए।यह समस्या कारण है c ++ में नाम स्थान है। वास्तव में एक ही नाम होने वाले 2 तीसरे पक्ष के काम के लिए सी में एक महान समाधान नहीं है।
यदि यह एक गतिशील वस्तु है, तो आप स्पष्ट रूप से साझा किए गए ऑब्जेक्ट्स (लोडलॉड / dlopen / etc) को लोड करने में सक्षम हो सकते हैं और इसे उस फैशन में कॉल कर सकते हैं। वैकल्पिक रूप से, यदि आपको एक ही कोड में एक ही समय में दोनों लिबास की आवश्यकता नहीं है, तो आप शायद स्थैतिक लिंकिंग के साथ कुछ कर सकते हैं (यदि आपके पास .lib / .a फाइलें हैं)।
इनमें से कोई भी समाधान निश्चित रूप से सभी परियोजनाओं पर लागू नहीं होता है।
कसम खाता? जहां तक मुझे जानकारी है, अगर आप दो पुस्तकालय हैं जो एक ही नाम के साथ लिंक बिंदुओं को उजागर करते हैं तो बहुत कुछ नहीं कर सकते हैं और आपको दोनों के खिलाफ लिंक करने की आवश्यकता है।
आपको उनमें से एक के आसपास एक रैपर लाइब्रेरी लिखना चाहिए। आपके रैपर लाइब्रेरी को अद्वितीय नामों के साथ प्रतीकों को उजागर करना चाहिए, और गैर-अद्वितीय नामों के प्रतीकों को उजागर नहीं करना चाहिए।
आपका अन्य विकल्प हैडर फ़ाइल में फ़ंक्शन नाम का नाम बदलना, और लाइब्रेरी ऑब्जेक्ट आर्काइव में प्रतीक का नाम बदलना है।
किसी भी तरह से, दोनों का उपयोग करने के लिए, यह एक हैक काम होने वाला है।
यह सवाल एक दशक पुराना है, लेकिन हर समय नई खोजें होती रहती हैं ...
जैसा कि पहले ही उत्तर दिया गया है, - theredefine-sym झंडा के साथ objcopy लिनक्स में एक अच्छा विकल्प है। उदाहरण के लिए, पूर्ण प्रलेखन के लिए https://linux.die.net/man/1/objcopy देखें । यह थोड़ा क्लिंकी है क्योंकि आप बदलाव करते समय अनिवार्य रूप से पूरी लाइब्रेरी की नकल कर रहे हैं और हर अपडेट के लिए इस काम को दोहराया जाना आवश्यक है। लेकिन कम से कम यह काम करना चाहिए।
विंडोज के लिए, गतिशील रूप से लाइब्रेरी को लोड करना एक समाधान है और लिनक्स में ड्लोपेन विकल्प की तरह एक स्थायी होगा। हालाँकि, दोनों dlopen () और LoadLibrary () अतिरिक्त कोड जोड़ते हैं, जिनसे बचा जा सकता है यदि केवल समस्या डुप्लिकेट नाम है। यहां विंडोज समाधान ओब्जेक्टोपी दृष्टिकोण से अधिक सुरुचिपूर्ण है: बस लिंकर को बताएं कि एक पुस्तकालय में प्रतीकों को किसी अन्य नाम से जाना जाता है और उस नाम का उपयोग करें। वहाँ कुछ कदम यह करने के लिए। आपको एक def फ़ाइल बनाने और EXPORTS अनुभाग में नाम अनुवाद प्रदान करने की आवश्यकता है। देखें https://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx (VS2015, यह अंततः नए संस्करणों के द्वारा बदल दिया जाएगा) या http://www.digitalmars.com/ctg/ctgDefFiles.html(शायद अधिक स्थायी) एक डीफ़ल फ़ाइल के पूर्ण वाक्यविन्यास विवरण के लिए। यह प्रक्रिया पुस्तकालयों में से किसी एक के लिए एक डिफ फ़ाइल बनाने के लिए होगी, फिर इस डीब फाइल का उपयोग एक लिबास फाइल बनाने के लिए करें और फिर उस लिबास फाइल के साथ लिंक करें। (विंडोज डीएलएल के लिए, लिब फाइल केवल लिंक करने के लिए उपयोग की जाती है, कोड निष्पादन के लिए नहीं।) देखें कि लिब फाइल बनाने की प्रक्रिया के लिए .dll फाइल और हेडर फाइल के लिए .lib फाइल कैसे बनाएं । यहाँ केवल अंतर एलियास को जोड़ रहा है।
लिनक्स और विंडोज दोनों के लिए, लाइब्रेरी के हेडर में उन कार्यों का नाम बदलें जिनके नाम अलियास किए जा रहे हैं। एक अन्य विकल्प जो काम करना चाहिए, वह होगा नए नामों के संदर्भ में, #define old_name new_name के लिए, # लायब्रेरी के हेडर को हटा दें, जिसका निर्यात अलियास किया जा रहा है, और फिर #undef old_name कॉलर में। यदि लाइब्रेरी का उपयोग करते हुए बहुत सारी फाइलें हैं, तो एक आसान विकल्प हैडर या हेडर बनाना जो डिफाइन, कवर और अनडेफ को लपेटता है और फिर उस हेडर का उपयोग करें।
आशा है कि यह जानकारी उपयोगी थी!
मैंने कभी भी dlsym, dlopen, dlerror, dlclose, dlvsym इत्यादि का उपयोग नहीं किया है, लेकिन मैं मैन पेज देख रहा हूं, और यह libm.so खोलने और कॉस फ़ंक्शन को निकालने का एक उदाहरण देता है। क्या dlopen टकरावों की तलाश की प्रक्रिया से गुजरता है? यदि ऐसा नहीं होता है, तो ओपी दोनों पुस्तकालयों को मैन्युअल रूप से लोड कर सकता है और उनके पुस्तकालयों द्वारा प्रदान किए जाने वाले सभी कार्यों को नए नाम प्रदान कर सकता है।