C#DllImport में 32bit या 64bit dll का उपयोग करना




.net pinvoke (5)

DLL फ़ाइल नाम रखने वाला एक स्थिर चर है

यह एक स्थिर चर नहीं है। यह एक स्थिर समय है। आप रनटाइम पर एक संकलन समय स्थिर नहीं बदल सकते।

इस मुद्दे से निपटने का सही तरीका क्या होगा?

ईमानदारी से, मैं केवल x86 को लक्षित करने और 64-बिट संस्करण को एक साथ भूल जाने की सलाह दूंगा, और आपके आवेदन को WOW64 पर चलने दूंगा, जब तक कि आपके आवेदन को x64 के रूप में चलाने की कोई आवश्यकता न हो।

यदि x64 की आवश्यकता है, तो आप निम्न कर सकते हैं:

  • DLL को बदल कर उसी नाम, जैसे MyDll.dll , और स्थापित / परिनियोजित समय पर, सही एक को रखें। (यदि ओएस x64 है, तो DLL के 64-बिट संस्करण को तैनात करें, अन्यथा x86 संस्करण)।

  • दो अलग बिल्ड पूरी तरह से है, एक x86 के लिए और एक x64 के लिए।

यहाँ स्थिति है, मैं अपने dot.net एप्लीकेशन में C आधारित dll का उपयोग कर रहा हूँ। 2 dll हैं, एक 32bit है जिसे MyDll32.dll कहा जाता है और दूसरा एक 64bit संस्करण है जिसे MyDll32.dll कहा जाता है।

DLL फ़ाइल का नाम रखने वाला एक स्थिर वैरिएबल है: string DLL_FILE_NAME।

और इसका उपयोग निम्नलिखित तरीके से किया जाता है:

[DllImport(DLL_FILE_NAME, CallingConvention=CallingConvention.Cdecl, EntryPoint=Func1")]
private static extern int is_Func1(int var1, int var2);

अब तक सरल।

जैसा कि आप कल्पना कर सकते हैं, सॉफ्टवेयर "किसी भी सीपीयू" के साथ संकलित है।

मेरे पास यह निर्धारित करने के लिए निम्न कोड है कि क्या सिस्टम को 64 बिट फ़ाइल या 32 बिट फ़ाइल का उपयोग करना चाहिए।

#if WIN64
        public const string DLL_FILE_NAME = "MyDll64.dll";
#else
        public const string DLL_FILE_NAME = "MyDll32.dll";        
#endif

अब तक आपको समस्या देखनी चाहिए .. DLL_FILE_NAME को संकलन समय में परिभाषित किया गया है न कि निष्पादन समय में इसलिए निष्पादन संदर्भ के अनुसार सही dll लोड नहीं किया गया है।

इस मुद्दे से निपटने का सही तरीका क्या होगा? मुझे दो निष्पादन फाइलें नहीं चाहिए (एक 32 बिट के लिए और दूसरी 64 बिट के लिए)? DllImport स्टेटमेंट में उपयोग करने से पहले मैं DLL_FILE_NAME को कैसे सेट कर सकता हूं?


आपके द्वारा वर्णित "साइड-बाय-साइड असेंबली" (एक ही असेंबली के दो संस्करण, एक 32 और दूसरा 64 बिट) के रूप में जाना जाता है ... मुझे लगता है कि आप इन सहायक पाएंगे:

Here आप अपने परिदृश्य के लिए एक वाकथ्रू पा सकते हैं (.NET DLL रैपिंग C ++ / CLI DLL एक देशी DLL का संदर्भ देते हुए)।

सिफ़ारिश करना:

बस इसे x86 के रूप में बनाएं और इसके साथ रहें ... या 2 बिल्ड (एक x86 और एक x 64) हैं ... जैसा कि उपरोक्त तकनीक जटिल हैं ...


एक वैकल्पिक तरीका हो सकता है

public static class Sample
{
    public Sample()
    {

        string StartupDirEndingWithSlash = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\";
        string ResolvedDomainTimeFileName = StartupDirEndingWithSlash + "ABCLib_Resolved.dll";
        if (!File.Exists(ResolvedDomainTimeFileName))
        {
            if (Environment.Is64BitProcess)
            {
                if (File.Exists(StartupDirEndingWithSlash + "ABCLib_64.dll"))
                    File.Copy(StartupDirEndingWithSlash + "ABCLib_64.dll", ResolvedDomainTimeFileName);
            }
            else
            {
                if (File.Exists(StartupDirEndingWithSlash + "ABCLib_32.dll"))
                    File.Copy(StartupDirEndingWithSlash + "ABCLib_32.dll", ResolvedDomainTimeFileName);
            }
        }
    }

    [DllImport("ABCLib__Resolved.dll")]
    private static extern bool SomeFunctionName(ref int FT);
}

मैंने एक दृष्टिकोण का उपयोग किया है जिसका अर्थ vcsjones द्वारा दिया गया है:

"DLL को उसी नाम से बदलें, जैसे MyDll.dll, और इंस्टॉल / परिनियोजित समय पर, सही एक को रखें।"

इस दृष्टिकोण को दो बिल्ड प्लेटफ़ॉर्म बनाए रखने की आवश्यकता है, हालांकि अधिक जानकारी के लिए इस लिंक को देखें: https://.com/a/6446638/38368


यहां एक और विकल्प है जिसके लिए आवश्यक है कि दो DLL का नाम एक ही हो और उन्हें अलग-अलग फ़ोल्डरों में रखा जाए। उदाहरण के लिए:

  • win32/MyDll.dll
  • win64/MyDll.dll

चाल CLR के होने से पहले DLL को LoadLibrary से मैन्युअल रूप से लोड करना है। फिर यह देखा जाएगा कि एक MyDll.dll पहले से ही लोड है और इसका उपयोग करें।

यह पैरेंट क्लास के स्टैटिक कंस्ट्रक्टर में आसानी से किया जा सकता है।

static class MyDll
{
    static MyDll()
    {            
        var myPath = new Uri(typeof(MyDll).Assembly.CodeBase).LocalPath;
        var myFolder = Path.GetDirectoryName(myPath);

        var is64 = IntPtr.Size == 8;
        var subfolder = is64 ? "\\win64\\" : "\\win32\\";

        LoadLibrary(myFolder + subfolder + "MyDll.dll");
    }

    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("MyDll.dll")]
    public static extern int MyFunction(int var1, int var2);
}

EDIT 2017/02/01 : Assembly.CodeBase उपयोग करें। कोडबेस्स ताकि यह छाया छायाकरण सक्षम होने पर भी काम करे।





dllimport