2012-05-25 141 views
4

我正在使用C#for .NET 4.0(通过Visual Studio 2010)编写的项目上工作。有第三方工具需要使用C/C++ DLL,并且在C#中有32位应用程序和64位应用程序的示例。使用Environment.Is64BitProcess从c#应用程序动态调用32位或64位DLL

问题是,32位演示静态链接到32位DLL和64位演示静态链接到64位DLL。作为一个.NET应用程序,它可以作为客户端PC上的32位或64位进程运行。

.NET 4.0框架提供了Environment.Is64BitProcess属性,该属性在应用程序作为64位进程运行时返回true。

我想要做的是在检查Is64BitProcess属性后动态加载正确的DLL。然而,当我研究动态加载库我总是能想出如下:

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

[DllImport("kernel32.dll")] 
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 

[DllImport("kernel32.dll")] 
public static extern bool FreeLibrary(IntPtr hModule); 

这样看来,这些方法是专门为32位操作系统。是否有64位等值?

只要基于Is64BitProcess检查调用适当的方法,是否会导致静态链接32位和64位库的问题?

public class key32 
{ 
    [DllImport("KEYDLL32.DLL", CharSet = CharSet.Auto)] 
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4); 

    public static bool IsValid() 
    { 
     ... calls KFUNC() ... 
    } 
} 

public class key64 
{ 
    [DllImport("KEYDLL64.DLL", CharSet = CharSet.Auto)] 
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4); 

    public static bool IsValid() 
    { 
     ... calls KFUNC() ... 
    } 
} 

...

if (Environment.Is64BitProcess) 
{ 
    Key64.IsValid(); 
} 
else 
{ 
    Key32.IsValid(); 
} 

谢谢!!

回答

1

具有讽刺意味的是,在64位系统上,kernel32.dll(位于%windir%\System32\)是64位版本,而%windir%\SysWOW64\版本是32位系统。非常不幸的命名会在这里......

无论如何,你可以做的是绑定到两个版本,使用的路径,因为我联系他们,两个不同的变量名称(比如,LoadLibrarysystem32版本和LoadLibrary32对于syswow64版本)。然后在32位系统上,您可以使用LoadLibrary,如果您检测到64位系统,则LoadLibrary将是64位版本,而LoadLibrary32将是32位版本。然而

我怀疑,这将有助于你任何,因为我不认为你可以动态绑定到失配位数(要补偿字!)动态库......将有助于你的第二个例子我想,在这里你实际上得到了两个不同的库,每个库都有一个库。

4

很多方法可以做到这一点:

  • 这是一个部署问题,刚刚获得由安装程序复制正确的DLL,给他们相同的名称

  • 很少有程序实际上需要64位代码提供的海量地址空间。只需将平台目标设置为x86

  • 使用[DllImport]属性的EntryPoint字段。将其设置为“KFUNC”。并给方法不同的名称。现在您可以根据IntPtr的值调用其中一个或另一个。大小

展示出最后的解决方案:

[DllImport("KEYDLL32.DLL", EntryPoint = "KFUNC")] 
private static extern uint KFUNC32(int arg1, int arg2, int arg3, int arg4); 

[DllImport("KEYDLL64.DLL", EntryPoint = "KFUNC")] 
private static extern uint KFUNC64(int arg1, int arg2, int arg3, int arg4); 

... 

if (IntPtr.Size == 8) KFUNC64(1, 2, 3, 4); 
else     KFUNC32(1, 2, 3, 4); 
0

而是这样做低级的互操作我会考虑去更多的.Net路线 - 使用插件式组件来处理它。

  • 创建2个程序集链接到x86和x64版本的DLL(并编译为正确的平台)。
  • 使此程序集公开实现相同接口的类(或使其相同的其他方式)。确保其余的代码可以使用任何一个库,可能需要使用基本类型/接口的第三个程序集。
  • 在运行时加载您手动需要的程序集。确保它不会出现在搜索路径中,以避免错误地自动加载一个。

请注意,你的第二种方法(基于比特度的采摘方法)应该可以正常工作。我仍然会将具有相同接口的类中的每个DLL的所有访问包括在内,并确保只有正确的一个可以在运行时实例化。

0

将dll保存在两个不同的目录中并动态调用它们。

Libs64 \ ABC.dll
Libs32 \ ABC.dll

相关问题