繁体   English   中英

根据 x64/x86 更改 C# DllImport 目标代码

[英]Change C# DllImport target code depending on 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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM