本文介绍在通过 P/Invoke 加载本机库时运行时搜索哪些路径。 它还演示如何使用
SetDllImportResolver
。
库名称变体
为了帮助简化跨平台 P/Invoke 代码,运行时将规范共享库扩展(
.dll
、
.so
或
.dylib
)添加到本机库名称。 在 Linux 和 macOS 上,运行时还将尝试在
lib
前添加。 使用加载非托管库(如
DllImportAttribute
)的 API 时,会自动搜索这些库名称变体。
库名称中的绝对路径(例如
/usr/lib/libc
)按原样处理,不会搜索任何变体。
请考虑以下使用 P/Invoke 的示例:
[DllImport("nativedep")]
static extern int ExportedFunction();
在 Windows 上运行时,将按以下顺序搜索 DLL:
nativedep
nativedep.dll(如果库名称尚未以 .dll 或 .exe 结尾)
在 Linux 或 macOS 上运行时,运行时将尝试在 lib 前添加,并追加规范共享库扩展。 在这些 OS 上,按以下顺序尝试库名称变体:
nativedep.so / nativedep.dylib
libnativedep.so / libnativedep.dylib1
nativedep
libnativedep1
在 Linux 上,如果库名称以 .so 结尾或包含 .so.(注意尾随 .),则搜索顺序会有所不同。 请考虑以下示例:
[DllImport("nativedep.so.6")]
static extern int ExportedFunction();
在这种情况下,将按以下顺序尝试库名称变体:
nativedep.so.6
libnativedep.so.61
nativedep.so.6.so
libnativedep.so.6.so1
1 仅当库名称不包含目录分隔符 (/) 时才检查路径。
自定义导入解析程序
在较复杂的方案中,可以使用 SetDllImportResolver 在运行时解析 DLL 导入。 在下面的示例中,nativedep 解析为 nativedep_avx2(如果 CPU 支持)。
此功能仅在 .NET 5 和 .NET Core 3.1 或更高版本中可用。
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace PInvokeSamples
public static class Program
[DllImport("nativedep")]
private static extern int ExportedFunction();
public static void Main(string[] args)
// Register the import resolver before calling the imported function.
// Only one import resolver can be set for a given assembly.
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), DllImportResolver);
int value = ExportedFunction();
Console.WriteLine(value);
private static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
if (libraryName == "nativedep")
// On systems with AVX2 support, load a different library.
if (System.Runtime.Intrinsics.X86.Avx2.IsSupported)
return NativeLibrary.Load("nativedep_avx2", assembly, searchPath);
// Otherwise, fallback to default import resolver.
return IntPtr.Zero;
平台调用 (P/Invoke)