.NET 5环境下Linux系统DllImport特性运行时动态修改库路径方案咨询
解决方案
方案1:使用.NET官方原生库解析器(推荐)
.NET 5 内置了NativeLibrary类,提供跨平台的原生库加载控制能力,其中SetDllImportResolver方法可以完全接管DllImport特性的库搜索逻辑,是SetDllDirectory的官方跨平台等价实现,适配你的所有场景。
实现步骤
- 在程序启动阶段、任何调用目标
DllImport方法的代码执行前,注册自定义解析逻辑 - 在解析逻辑中根据当前操作系统拼接对应路径的原生库完整路径,主动加载后返回句柄即可
代码示例
using System.Runtime.InteropServices; using System.Reflection; // 你的DllImport声明示例,库名统一写不带前缀后缀的名称即可 [DllImport("MyDriver")] public static extern int MyDriverMethod(); // 程序初始化时调用一次即可,winDriverVersion参数用来切换Windows下1/2两个路径的驱动 public static void InitNativeSearchPath(int winDriverVersion = 1) { string baseLibDir = Environment.CurrentDirectory; string targetLibDir; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { targetLibDir = Path.Combine(baseLibDir, "Drivers", "Win", winDriverVersion.ToString()); // 兼容原有Windows逻辑 SetDllDirectory(targetLibDir); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { targetLibDir = Path.Combine(baseLibDir, "Drivers", "Linux"); } else { throw new PlatformNotSupportedException(); } // 注册当前程序集的DllImport解析器 NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (libName, assembly, searchPath) => { // 仅处理自定义的驱动库,其他系统库走默认逻辑 if (libName != "MyDriver") return IntPtr.Zero; string fullLibPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Path.Combine(targetLibDir, $"{libName}.dll") : Path.Combine(targetLibDir, $"lib{libName}.so"); return NativeLibrary.TryLoad(fullLibPath, out var libHandle) ? libHandle : IntPtr.Zero; }); } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool SetDllDirectory(string lpPathName);
方案2:修改LD_LIBRARY_PATH环境变量(简单场景可用)
Linux系统原生的动态库搜索路径会读取LD_LIBRARY_PATH环境变量,你可以在程序启动后、第一次调用目标DllImport方法前,修改当前进程的环境变量,把你的so库路径添加进去:
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var libPath = Path.Combine(Environment.CurrentDirectory, "Drivers", "Linux"); var oldLdPath = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH") ?? string.Empty; Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", $"{libPath}:{oldLdPath}"); }
注意:该方案仅在第一次加载原生库前修改环境变量生效,如果已经加载过原生库,运行时会缓存搜索路径,修改不会生效,因此仅适合启动时就确定库路径的简单场景,复杂场景优先使用方案1。
运行时切换驱动路径适配说明
如果需要在运行时切换Windows下1和2两个路径的dll,只需要把方案1中的targetLibDir修改为可修改的静态变量,切换路径后调用NativeLibrary.Free释放已加载的旧库句柄,下次调用DllImport方法时就会自动加载新路径的库。
内容的提问来源于stack exchange,提问作者FriendOfFriend
相关产品推荐
相关产品推荐

