Setting dllimport programmatically in C#

2019-02-05 04:05发布

I am using DllImport in my solution.
My problem is that I have two versions of the same DLL one built for 32 bit and another for 64 bit.

They both expose the same functions with identical names and identical signatures. My problem is that I have to use two static methods which expose these and then at run time use IntPtr size to determine the correct one to invoke.

private static class Ccf_32
{
    [DllImport(myDllName32)]
    public static extern int func1();
}

private static class Ccf_64
{
    [DllImport(myDllName64)]
    public static extern int func1();
}

I have to do this because myDllName32 and myDllName64 must be constant and I have not found a way to set it at run time.

Does anyone have an elegant solution for this so I could get rid of the code duplication and the constant IntPtr size checking.

If I could set the file name, I would only have to check once and I could get rid of a ton of repeated code.

9条回答
霸刀☆藐视天下
2楼-- · 2019-02-05 04:38

One alternative option is to have both the 32- and 64-bit versions of the unmanaged DLL have the same name, but have them live in separate folders in your build output (say, x86\ and x64\).

Then, your installer or however else you're distributing this is updated so it knows to install the proper DLL for the platform it's installing on.

查看更多
放我归山
3楼-- · 2019-02-05 04:39

you can create two methods and choose one in a runtime, so you can keep Any CPU

public static class Ccf
{
    [DllImport(myDllName32)]
    private static extern int func32();

    [DllImport(myDllName64)]
    private static extern int func64();


    public static int func()
    {
        if(Environment.Is64BitProcess)
        {
            return func64();
        }
        return func32();
    }

}

查看更多
Ridiculous、
4楼-- · 2019-02-05 04:41

You can probably achieve this with the #if keyword. If you define a conditional compiler symbol called win32, the following code will use the win32-block, if you remove it it will use the other block:

#if win32
    private static class ccf_32
    {
        [DllImport(myDllName32)]
        public static extern int func1();
    }
#else    
    private static class ccf_64
    {
        [DllImport(myDllName64)]
        public static extern int func1();
    }
#endif

This probably means that you can remove the class wrapping that you have now:

    private static class ccf
    {
#if win32
        [DllImport(myDllName32)]
        public static extern int func1();
#else    
        [DllImport(myDllName64)]
        public static extern int func1();
#endif
    }

For convenience, I guess you could create build configurations for controlling the compilation symbol.

查看更多
等我变得足够好
5楼-- · 2019-02-05 04:43

Why not wrap them into a method?

private static class ccf_32_64
{
    private static class ccf_32
    {
        [DllImport(myDllName32)]
        private static extern int func1();
    }

    private static class ccf_64
    {
        [DllImport(myDllName64)]
        private static extern int func1();
    }

    public static int func1()
    {
        if (32bit)
        {
            return ccf_32.func1();
        }
        else
        {
            return ccf_64.func1();
        }
    }
}
查看更多
地球回转人心会变
6楼-- · 2019-02-05 04:47

You can determine whether you are running 64Bits or not by checking the size of the IntPtr type (which is called native int anyways). Then you can load the approriate DLL using an imported LoadLibraryW call, get the function pointer using GetProcAddress, and then, check out Marshal.GetDelegateForFunctionPointer

This not nearly as complicated as it might look like. You have to DllImport both LoadLibraryW and GetProcAddress.

查看更多
做自己的国王
7楼-- · 2019-02-05 04:48

Hmm, I'm wondering if you could create an interface and then a class with the methods based on the 32 bit and 64 bit dlls.

I'm not sure if there is an explicit method to determine if you are running 64 bit, but the following might work: allow unsafe code and have an unsafe function that gets a pointer to some address and then determine whether the pointer is 4 or 8 bytes in size. Based on the result determine which implementation of the interface to create.

查看更多
登录 后发表回答