2008-11-24 10 views
11

मैं दो वाणिज्यिक पुस्तकालयों का उपयोग कर रहा हूं जो वही विक्रेता द्वारा उत्पादित होते हैं, जिन्हें वेंडर लिबा और वेंडरलिब कहा जाता है। पुस्तकालयों को कई डीएलएल के रूप में वितरित किया जाता है जो संकलक संस्करण (उदा। वीसी 7, वीसी 8) पर निर्भर करते हैं। दोनों पुस्तकालय एक अन्य पुस्तकालय पर निर्भर करते हैं, जो इस विक्रेता द्वारा उत्पादित किया जाता है, जिसे वेंडरलिब्यूट कहा जाता है और एक डीएलएल में निहित होता है।क्या मैं एक ही प्रक्रिया में एक ही डीएलएल के दो असंगत संस्करणों का उपयोग कर सकता हूं?

समस्या: VendorLibA VendorLibB से VendorLibUtils का एक अलग संस्करण का उपयोग करता। दो संस्करण बाइनरी संगत नहीं हैं, और भले ही वे गलत संस्करण का उपयोग करना एक बुरा विचार होगा।

वहाँ किसी भी तरह से मैं एक ही प्रक्रिया के तहत दो पुस्तकालयों इस्तेमाल कर सकते हैं है?

नोट: लोड लाइब्रेरी इसे हल नहीं कर सकता है क्योंकि मेरी प्रक्रिया वह नहीं है जो विक्रेता विक्रेता आयात कर रही है।

संपादित करें:, स्पष्ट उल्लेख करना भूल मैं वाणिज्यिक पुस्तकालयों में से किसी के लिए स्रोत कोड की जरूरत नहीं है और शायद मैं कभी नहीं होगा (आह)।

संपादित करें: विकल्प btw, यह करने के लिए है: DLLs में How to combine GUI applications in Windows

+0

वाह। चारों ओर एक बुरी स्थिति की तरह लगता है। वहाँ पर लटका हुआ। – ahockley

उत्तर

3

आप VendorLibUtils सीधे उपयोग नहीं कर रहे हैं, मुझे लगता है आप LoadLibrary आदि

उपयोग नहीं कर सकते VendorLibUtils DLLs केवल क्रमसूचक द्वारा निर्यात किया है, तो आप शायद पुस्तकालयों में से एक का नाम बदलने सकता है और पैच इसी VendorLib एक्स इसके आयात के लिए एक अलग फ़ाइल नाम का उपयोग करने के लिए।

यदि विक्रेता लिब्यूट्स डीएलएल के पास एक ही नाम के साथ एक या अधिक निर्यात किए गए प्रतीकों हैं, तो आप आयात और निर्यात तालिकाओं को भी पैच करने की आवश्यकता है, लेकिन उम्मीद है कि नहीं! :-)

+0

नाम से निर्यात यह है: /। इसके लिए कोई Google खोज शब्द? – kshahar

+0

एक परीक्षण एप्लिकेशन और चार डीएलएल बनाएं जो इस परिदृश्य को पुन: उत्पन्न करते हैं, यह देखने के लिए कि क्या आपके पास दो "टेस्टलिब्यूट्स" डीएलएल में समान प्रतीक नाम हो सकता है और टेस्टलिबा और टेस्टलिब सही कार्य चलाता है। –

2

मैं कोई विशेषज्ञ है, लेकिन एक ही रास्ता मैं यह संभव देख LoadLibrary() उपयोग करने के लिए और स्पष्ट रूप से DLLs लोड होगा। फिर आप GetProcAddress() का उपयोग करके अलग-अलग नामस्थानों में फ़ंक्शंस/क्लासेस इत्यादि रख सकते हैं।

HMODULE v1 = LoadLibrary(_T("libv1_0.dll")); 
libv1_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v1, _T("fun_in_lib")); 

और

HMODULE v2 = LoadLibrary(_T("libv2_0.dll")); 
libv2_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v2, _T("fun_in_lib")); 

इस काम करेगा या नहीं अभी भी एक तरह से पुस्तकालय पर निर्भर करता है, तो यह या काम नहीं कर सकता सकता है, लेकिन जहाँ तक मैं बता सकता है यह केवल संभावना है या नहीं।

5

मुझे लगता है कि आपके सबसे आशाजनक विकल्प परस्पर असंगत उत्पादों को वितरित करने वाले विक्रेता को जोर से शिकायत करना है। यह एक डीएलएल के विचार के खिलाफ चला जाता है।

आप डीएलएल को अलग-अलग निर्देशिका में नहीं डाल सकते हैं। एक बार दिए गए नाम के साथ एक डीएलएल लोड हो जाने के बाद, एक ही मॉड्यूल नाम के साथ एक और डीएलएल लोड करने के सभी अन्य प्रयासों का उपयोग केवल उस व्यक्ति का उपयोग करेगा जो पहले ही लोड हो चुका है, भले ही पथ अलग हैं।

कि से

, हम VendorLibUtils की दो प्रतियां लोड करने के लिए है कि निष्कर्ष निकाल सकते हैं, एक प्रति एक अलग नाम की जरूरत है। आप सिर्फ डीएलएल फ़ाइल का नाम बदल नहीं सकते; आपके प्रोग्राम में कोड अलग-अलग फाइल को देखने के लिए नहीं पता होगा। इसलिए, शायद VendorLibUtils.dll की बजाय VendorLibUtilsB.dll में यह आवश्यक कार्य करने के लिए वेंडरलिब की आयात तालिका को संपादित करने का एक तरीका है।मुझे डर है कि मुझे किसी भी उपयोगिता के बारे में पता नहीं है जो ऐसा करेगा, लेकिन मुझे कोई संदेह नहीं है कि ऐसा करना संभव है।

2

किसी और उल्लेख किया है, आप VendorLibUtils की प्रतियों में से एक का नाम बदलने और बजाय VendorLibUtils.dll इसके साथ बनाया गया था इसे करने के लिए लिंक करने के लिए, जुड़े VendorLib DLL के आयात तालिका को संशोधित कर सकता है।

वहाँ वहाँ बाहर कुछ उपकरण आप इस तरह से EXE/DLL फ़ाइलों को संपादित करते हैं कि है। CFF Explorer एक सुंदर सभ्य है जो आयात तालिका के संपादन की अनुमति देता है। आप इसे में VendorLib DLL खुल जाएगा और आयात निर्देशिका खंड (बाईं ओर पेड़ में) करने के लिए जाना है, तो आप मुख्य विंडो के शीर्ष पर मॉड्यूल की एक सूची दिखाई देगी। आप मॉड्यूल का नाम अपने नाम पर डबल-क्लिक करके कर सकते हैं। फिर आप केवल डीएलएल को सहेजते हैं और अब इसे अपने नामित वेंडरलिब्यूट्स डीएलएल का उपयोग करना चाहिए। यह LoadLibrary/GetProcAddress, जिस स्थिति में आप VendorLibUtils के लिए एक आयात तालिका प्रविष्टि नहीं देखेंगे उपयोग कर सकते हैं -

बेशक

, इस कि VendorLib VendorLibUtils है, जो यह नहीं हो सकता तक पहुँचने के लिए आयात तालिका का उपयोग करता हो जाती है।

वास्तव में, VendorLib आयात तालिका लेकिन भीLoadLibrary का उपयोग करता है कुछ स्थानों में VendorLibUtils DLL पहुँचने के लिए उपयोग करता है, तो (मैं इसे किया देखा है), उन स्थानों अभी भी गलत एक का प्रयोग करेंगे। यदि आप दोनों पुस्तकालयों का नाम बदलते हैं, तो कम से कम एक त्रुटि दिखाई दे सकती है यदि यह मामला है (चूंकि मूल नाम वाला डीएलएल अब मौजूद नहीं होगा)। यदि ऐसा होता है तो इसका निपटारा करने का एक तरीका है, लेकिन इस बिंदु पर यह काफी जटिल हो जाता है, इसलिए जब तक आप वास्तव में जानना नहीं चाहते हैं तब तक मैं विस्तृत नहीं करूंगा।

1

तुम्हारा मतलब है, आप एक स्थिति MSVCRT80.DLL और MSVCRT90.DLL के समान है? माइक्रोसॉफ्ट ने इन डीएलएल को गिने जाने का एक अच्छा कारण बताया है। अगर दोनों को एमएसवीसीआरटी.डीएलएल कहा जाता है, तो उनमें से केवल एक ही प्रक्रिया में लोड किया जाएगा।

+0

मेरी स्थिति वह है जहां डीएलएल को एमएसवीसीआरटी.डीएलएल कहा जाता है, लेकिन उनकी सामग्री में अलग हैं। – kshahar

0

यह वास्तव में परोक्ष एक भी प्रक्रिया में एक dll के विभिन्न संस्करणों लोड करने के लिए संभव है।

ऐसा जरूरत पर जोर देता:

  1. दो विधानसभाओं बनाना, प्रत्येक dll कि कई बार लोड किया जाना चाहिए का एक संस्करण से युक्त। जटिल लगता है लेकिन व्यावहारिक रूप से इसमें उप-फ़ोल्डर नामक (2) बनाने से थोड़ा अधिक शामिल होता है, प्रत्येक में एक .manifest फ़ाइल होती है जिसमें कुछ एक्सएमएल होता है, और इसकी डीएल की अपनी प्रति होती है। तो, VendorUtilsAssemblyV1 और VendorUtilsAssemblyV2

  2. बनाना प्रत्येक निर्भर dll निहित निर्भरता को हल करने विधानसभा तंत्र का उपयोग - एक assemblyDependency निर्देश है कि स्पष्ट रूप से VendorUtilsAssemblyV1 या V2 की पहचान करता है जोड़कर।

वहाँ बिंदु 2 के लिए कुछ विकल्प VendorLibA और VendorLibB फ़ाइलों को अपने स्वयं प्रकट होता है शामिल नहीं है, तो आप बस प्रकट फ़ाइलों VendorLibA.2.dll.manifest और VendorLibB नामित आवश्यक dependentAssembly निर्देश के साथ जोड़ सकते हैं कर रहे हैं .2.dll.manifest। वे पहले से ही प्रकट होता है शामिल है तो (शायद VS2005 या VS2008 सी क्रम से जोड़ने के लिए) तो नए निर्भरता में विलय करने के लिए MT.EXE उपकरण का उपयोग।

4

मैं एक ऐसी ही समस्या थी। विशेष रूप से मैं एक Python दुभाषिया से एक PyQt का उपयोग करना चाहता था जो एक अनुप्रयोग में एम्बेडेड Qt के एक असंगत संस्करण का उपयोग कर रहा था। प्राथमिक अनुप्रयोग द्वारा उपयोग किए गए दो क्यूटी डीएलएल थे: QtCore.dll और QtGui.dll।

ImportError: DLL load failed: The specified procedure could not be found. 

इस लाइन पर हुआ::

जब मैं एम्बेडेड पायथन दुभाषिया से PyQt लोड होता है, मैं एक त्रुटि मिलेगा

from PyQt4 import QtGui 

समस्या यह है कि एक बार एक असंगत QtGui .dll मुख्य अनुप्रयोग की प्रक्रिया स्थान में लोड किया गया है QtGui.dll (जैसे फ़ाइल QtGui.pyd से) के किसी भी संदर्भ गलत हैं।

आगे क्या हुआ, मुझे गर्व नहीं है।

First I renamed QtGui4.dll in the PyQt distribution to QtGuiX.dll and then renamed the QtCore4.dll to QtCoreX.dll . Notice that the renaming maintained the same number of characters, this is important.

Next I opened the file QtGui.pyd in Notepad++, and replaced all plain-text references of QtGui4.dll to QtGuiX.dll and from QtCore4.dll to QtCoreX.dll . I repeated the process for the files: QtCore.pyd , QtGuiX.dll and QtCoreX.dll .

Finally I checked that my PyQt test application still worked. It did! Then I tried running the PyQt test application from the embedded Python interpreter, and it worked as well.

So, it seems to works in a couple of trivial cases. I expect that I need to repeat the process for all DLLs and PYDs in the PyQt distribution.

यह शायद काम करने के लिए सही रास्ता नहीं है, लेकिन मैं कोई ठोस कारण से नहीं सोच सकते हैं कि यह कैसे उड़ा सकता है (के अलावा अन्य अगर मैं फ़ाइल नाम की लंबाई को बदल)।

इस भयानक कहानी को प्रेरणा देने के लिए धागे पर दूसरों को क्रेडिट (या दोष)।

+0

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

+0

@ FrançoisBeaune मुझे यह खेद करने के लिए कोई बेहतर तरीका नहीं पता है। – cdiggins

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

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