4

I am working on a project written in C# for .NET 4.0 (via Visual Studio 2010). There is a 3rd party tool that requires the use of a C/C++ DLL and there are examples for 32-bit applications and 64-bit applications in C#.

The problem is that the 32-bit demo statically links to the 32-bit DLL and the 64-bit demo statically links to the 64-bit DLL. Being a .NET application it could run as either a 32-bit or 64-bit process on the client PCs.

The .NET 4.0 framework provides the Environment.Is64BitProcess property that returns true if the application is running as a 64-bit process.

What I would like to do is to dynamically load the correct DLL after checking the Is64BitProcess property. However, when I research dynamically loading libraries I always come up with the following:

[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);

It would appear that these methods are specifically for the 32-bit operating system. Are there 64-bit equivalents?

Would it cause problems to statically link both the 32-bit and 64-bit libraries as long as the appropriate methods are called based on the Is64BitProcess check?

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();
}

Thank you!!

4

4 回答 4

4

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

  • 这是一个部署问题,只需获取安装程序复制的正确 DLL,给它们起相同的名称

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

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

演示最后一个解决方案:

[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);
于 2012-05-25T16:31:24.843 回答
1

讽刺的是,在 64 位系统上,kernel32.dll(驻留在 中%windir%\System32\)是 64 位版本,而%windir%\SysWOW64\版本是 32 位系统。非常不幸的命名在这里发生......

无论如何,您可以做的是绑定到两个版本,使用我链接它们的路径,绑定到两个不同的变量名称(例如,LoadLibrary版本system32LoadLibrary32版本syswow64)。然后在 32 位系统上就可以使用LoadLibrary,如果检测到 64 位系统,LoadLibrary将是 64 位版本,而LoadLibrary32将是 32 位版本。

然而,我质疑这会对你有所帮助,因为我认为你不能动态绑定到不匹配的位数(我会用这个!)动态库......我猜这会帮助你的第二个例子,你实际上确实得到了两个不同的库,每个案例一个。

于 2012-05-25T16:30:19.370 回答
0

我不会这样做低级互操作,而是考虑使用更多的 .Net 路由 - 使用类似插件的程序集来处理它。

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

请注意,您的第二种方法(基于位数选择方法)应该可以正常工作。我仍然会将对每个 DLL 的所有访问封装在具有相同接口的类中,并确保在运行时只能实例化正确的一个。

于 2012-05-25T16:33:16.590 回答
0

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

Libs64\ABC.dll
Libs32\ABC.dll

于 2017-09-11T15:27:51.123 回答