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

问题描述 投票:15回答:2

我有一个使用DLLImport导入的外部c ++ dll。如果我的应用程序在x64中编译,我需要导入这个dll的x64版本,如果是x86版本,我需要x86 dll。

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

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

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

c# c-preprocessor windows-7-x64 dllimport
2个回答
23
投票

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

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

但没有人喜欢这样做。较不痛苦的方法是将函数声明两次,赋予它不同的名称,并使用[DllImport]属性中的EntryPoint属性指定实名。然后在运行时测试您要调用的内容。

但没有人喜欢这样做。最有效的技巧是引导Windows为您加载正确的DLL。首先要做的是将DLL复制到Windows不会查找的目录中。最好的方法是在构建目录中创建“x86”和“x64”子目录,并将相应的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位模式运行对您是否真的有用。很少需要从中获得巨大的虚拟内存地址空间,这是唯一真正的好处。您仍需要支持需要在2 GB情况下正常运行的32位版本。


5
投票

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

或者,设置2个不同的构建配置 - 一个只执行x86,另一个只执行x86_64,为每个构建配置一个条件编译符号,并在自定义符号上使用#ifdef。

© www.soinside.com 2019 - 2024. All rights reserved.