如何在运行时动态选择DllImport的加载路径以适配32/64位不同DLL
最优实现方案(代码改动量极小,无需修改原有P/Invoke声明)
该方案完全适配你需要最小化代码改动、方便合并上游更新的需求,原有项目中所有的[DllImport]声明、外部方法调用逻辑不需要做任何修改,仅需在程序入口处添加少量初始化代码即可:
步骤1:整理原生DLL文件
将32位DLL重命名为你原DllImport中NativeLibraryName对应的文件名(比如你原代码定义为const string NativeLibraryName = "MyNative.dll",就统一命名为MyNative.dll),放在程序根目录的x86子文件夹中;64位DLL同样命名为MyNative.dll,放在程序根目录的x64子文件夹中。
步骤2:添加启动时动态设置DLL搜索路径逻辑
在程序入口方法(比如Program.Main)的最开头添加以下代码:
using System; using System.IO; using System.Runtime.InteropServices; // 导入Windows系统DLL搜索路径配置API,跨平台场景可对应替换为系统对应接口 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool SetDllDirectory(string lpPathName); static void Main(string[] args) { // 执行原有逻辑前先配置正确的DLL搜索路径 string archDirectory = Environment.Is64BitProcess ? "x64" : "x86"; string dllSearchPath = Path.Combine(AppContext.BaseDirectory, archDirectory); SetDllDirectory(dllSearchPath); // 原有业务逻辑完全保留,无需改动 // ... }
.NET Core 3.0/.NET 5+ 专属优化方案
如果你使用的是高版本.NET runtime,还可以用原生提供的DllImport解析器实现,连目录分层都不需要,两个不同位数的DLL可以直接放在程序根目录用不同名称命名,同样不需要修改原有P/Invoke声明:
using System.Reflection; using System.Runtime.InteropServices; static void Main(string[] args) { // 注册自定义DLL导入解析逻辑 NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (libraryName, assembly, searchPath) => { // 仅处理目标原生库的解析,其他库走默认逻辑 if (libraryName == NativeLibraryName) { string realDllName = Environment.Is64BitProcess ? "MyNative_x64.dll" : "MyNative_x86.dll"; return NativeLibrary.Load(Path.Combine(AppContext.BaseDirectory, realDllName)); } return IntPtr.Zero; }); // 原有业务逻辑完全保留 // ... }
以上两种方案的所有新增代码都集中在程序入口位置,和原有业务代码、P/Invoke声明完全隔离,后续合并上游项目更新时不会产生任何冲突。
内容的提问来源于stack exchange,提问作者GameDevAlien
相关产品推荐
相关产品推荐

