我有一个要使用 DLLImport 导入的外部 c++ dll。如果我的应用程序在 x64 中编译,我需要导入这个 dll 的 x64 版本,如果它是 x86 版本,我需要 x86 dll。
实现这一目标的最佳方法是什么?
理想情况下,我想要一些预处理器指令,但我知道这在 c# 中不起作用?
更多信息:DLL 正在由设置为 AnyCPU 的项目导入。父项目是决定应用程序编译为 x64 还是 x86 的项目。我们为不同的客户编译了两个版本——我想在两个版本中共享子项目。
我有一个要使用 DLLImport 导入的外部 c++ dll。如果我的应用程序在 x64 中编译,我需要导入这个 dll 的 x64 版本,如果它是 x86 版本,我需要 x86 dll。
实现这一目标的最佳方法是什么?
理想情况下,我想要一些预处理器指令,但我知道这在 c# 中不起作用?
更多信息:DLL 正在由设置为 AnyCPU 的项目导入。父项目是决定应用程序编译为 x64 还是 x86 的项目。我们为不同的客户编译了两个版本——我想在两个版本中共享子项目。
这主要是一个部署问题,只需让您的安装程序根据目标计算机上的 Windows 版本复制正确的 DLL。
但没有人喜欢这样做。动态地调用正确的 DLL 函数非常痛苦,您必须为每个导出的函数编写委托类型并使用 LoadLibrary + GetProcAddress + Marshal.GetDelegateForFunctionPointer 来创建委托对象。
但没有人喜欢这样做。较不痛苦的方法是声明函数两次,给它不同的名称,并使用 [DllImport] 属性中的 EntryPoint 属性来指定真实名称。然后在您要调用的运行时进行测试。
但没有人喜欢这样做。最有效的技巧是引导 Windows 为您加载正确的 DLL。您要做的第一件事是将 DLL 复制到 Windows 不会查找它的目录中。最好的方法是在构建目录中创建一个“x86”和一个“x64”子目录,并将适当的 DLL 复制到每个子目录中。通过编写一个创建目录并复制 DLL 的构建后事件来做到这一点。
然后通过调用 SetDllDirectory() 告诉 Windows。您指定的路径将被添加到 Windows 搜索 DLL 的目录中。像这样:
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
class Program {
static void Main(string[] args) {
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
path = Path.Combine(path, IntPtr.Size == 8 ? "x64" : "x86");
bool ok = SetDllDirectory(path);
if (!ok) throw new System.ComponentModel.Win32Exception();
//etc..
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetDllDirectory(string path);
}
请考虑让代码在 64 位模式下运行是否真的对您有用。很少需要从中获得巨大的虚拟内存地址空间,这是唯一真正的好处。您仍然需要支持需要在 2 GB 情况下正常运行的 32 位版本。
添加具有不同名称的 x86 和 x86_64 DLL 导入,然后您可以根据运行时的体系结构有条件地调用它们,方法是检查 Environment.Is64BitProcess(或 IntPtr.size,如果您使用的是 < .Net 4)的值。无论项目是构建为 x86、x86_64 还是 AnyCPU,这都将起作用
或者,设置 2 种不同的构建配置 - 一种仅适用于 x86,另一种仅适用于 x86_64,为每个配置提供条件编译符号并在自定义符号上使用 #ifdef。