根据x64/x86更改C#DllImport目标代码 我有一个使用dLimPART导入的外部C++ DLL。如果我的应用程序是用x64编译的,我需要导入此dll的x64版本;如果它是x86版本,我需要x86 dll

根据x64/x86更改C#DllImport目标代码 我有一个使用dLimPART导入的外部C++ DLL。如果我的应用程序是用x64编译的,我需要导入此dll的x64版本;如果它是x86版本,我需要x86 dll,c#,dllimport,windows-7-x64,C#,Dllimport,Windows 7 X64,实现这一目标的最佳方式是什么 理想情况下,我想要一些预处理器指令,但我知道这在c#中不起作用 更多信息:DLL由设置为AnyCPU的项目导入。父项目决定应用程序编译为x64还是x86。我们为不同的客户编译这两个版本-我想在这两个版本中共享子项目。添加具有不同名称的x86和x86_64 DLL导入,然后您可以在运行时通过检查Environment.Is64BitProcess的值根据体系结构有条件地调用它们(如果您使用的是

实现这一目标的最佳方式是什么

理想情况下,我想要一些预处理器指令,但我知道这在c#中不起作用


更多信息:DLL由设置为AnyCPU的项目导入。父项目决定应用程序编译为x64还是x86。我们为不同的客户编译这两个版本-我想在这两个版本中共享子项目。

添加具有不同名称的x86和x86_64 DLL导入,然后您可以在运行时通过检查Environment.Is64BitProcess的值根据体系结构有条件地调用它们(如果您使用的是<.Net 4,则为IntPtr.size)。无论项目是以x86、x86_64还是AnyCPU的形式构建的,这都将起作用


或者,设置两种不同的生成配置—一种只执行x86,另一种只执行x86_64,给每种配置一个条件编译符号,并在自定义符号上使用#ifdef。

这主要是部署问题,只需让安装程序根据目标计算机上的Windows版本复制正确的DLL即可

但是没有人喜欢这样做。动态输入正确的DLL函数非常痛苦,您必须为每个导出的函数编写委托类型,并使用LoadLibrary+GetProcAddress+Marshal.GetDelegateForFunctionPointer创建委托对象

但从来没有人喜欢这样做。不那么痛苦的做法是两次声明函数,给它不同的名称,并使用[DllImport]属性中的EntryPoint属性指定真实名称。然后在运行时测试要调用的函数

但没有人喜欢这样做。最有效的技巧是引导Windows为您加载正确的DLL。您要做的第一件事是将DLL复制到Windows不会查找它的目录中。最好的方法是创建一个“x86”和一个“x64”并将相应的DLL复制到每个DLL中。为此,请编写生成后事件,创建目录并复制DLL

然后通过pinvoking 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位模式下运行对你来说确实是有用的。它非常罕见,需要从它那里得到的巨大虚拟内存地址空间,这是唯一真正的好处。你仍然需要支持32位版本,它需要在2千兆字节的情况下正确运行。

导入两个版本(私有方法)但要根据环境向客户端代码公开正确的代码,请使用.NET 4。注意,由于依赖本机DLL,我不会保留两个不同版本的C#应用程序(因此我不会为此使用预处理器).Michael-这几乎是我的问题,但我还有一个额外的复杂问题,这意味着他们的解决方案无法工作。我的dll是由一个名为anycpu的项目导入的,父项目决定应用程序是x64还是x64x86@Sugrue然后您需要使用运行时解决方案,即同时导入和使用
环境.Is64BitProcess
,或
sizeof(无效*)
,或
IntPtr.Size
。这是唯一的方法吗?我希望有更优雅的东西。我想OP可能会重复我想OP不知道如何使用
#ifdef
你能为他提供一个快速的代码示例,也许还有一个加载库的代码示例吗?尽管没有示例,仍然给出了+1。
环境64BitProcess
真的帮了我一把,感谢这个解决方案。PhonicUK和Michael Graczyk也有很好的解决方案,但这个解决方案不涉及重复的代码,这是我喜欢的。就我个人而言,我更喜欢显式调用
LoadLibrary
传递完整路径,而不是修改DLL搜索路径,这对我来说总是很笨拙。基本的想法是当然相同。LoadLibrary包含在第二段中。不好的主意。@HansPassant不太好:在调用Method1()之前,您可以声明normal[DllImport(“myLibrary.dll”]extern static void Method1();并将LoadLibrary与LoadLibrary(“c:\temp\amd64\myLibrary.dll”)这样的完整路径一起使用pinvoke和windows将使用已加载的myLibrary.dll