相关文章推荐
爱旅游的山寨机  ·  maps - API key ...·  2 年前    · 
沉稳的围巾  ·  python3 ...·  3 年前    · 

本文介绍在通过 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)
  •