Megosztás a következőn keresztül:


Natív kódtár betöltése

Ez a cikk bemutatja, hogy a futtatókörnyezet mely útvonalakon keres natív kódtárak P/Invoke használatával való betöltésekor. Azt is bemutatja, hogyan kell használni SetDllImportResolver.

Kódtárnév-változatok

A platformfüggetlen P/Invoke kód egyszerűbb megkönnyítése érdekében a futtatókörnyezet hozzáadja a canonical shared library bővítményt (.dll.sovagy .dylib) a natív kódtárnevekhez. Unix-alapú platformokon a futtatókörnyezet is megpróbálja az előfeltűnést lib. Ezek a kódtárnevek-változatok automatikusan keresnek, amikor natív kódtárakat töltő API-kat használ, például DllImportAttribute.

Feljegyzés

A kódtárnevek abszolút elérési útjai (például ) a következőképpen vannak kezelve, /usr/lib/libc.soés a rendszer nem keres változatokat.

Vegye figyelembe a P/Invoke használatát az alábbi példában:

[DllImport("nativedep")]
static extern int ExportedFunction();

Windows rendszeren való futtatáskor a DLL a következő sorrendben lesz keresve:

  1. nativedep
  2. nativedep.dll (ha az erőforrástár neve még nem végződik vagy .dll .exe)

Linux vagy macOS rendszeren való futtatáskor a futtatókörnyezet megpróbálja előre felerősíteni lib és hozzáfűzni a canonical megosztott kódtárbővítményt. Ezeken az operációs rendszereken a kódtárnév-változatok a következő sorrendben próbálkoznak:

  1. nativedep.so / nativedep.dylib
  2. libnativedep.so / libnativedep.dylib1
  3. nativedep
  4. libnativedep1

Linuxon a keresési sorrend eltérő, ha a kódtár neve végződik .so vagy tartalmaz .so. (jegyezze fel a zárót .). Vegyük a következő példát:

[DllImport("nativedep.so.6")]
static extern int ExportedFunction();

Ebben az esetben a kódtárnév-változatok a következő sorrendben próbálkoznak:

  1. nativedep.so.6
  2. libnativedep.so.61
  3. nativedep.so.6.so
  4. libnativedep.so.6.so1

1 Az elérési út csak akkor van bejelölve, ha az erőforrástár neve nem tartalmaz könyvtárelválasztó karaktert (/).

Egyéni importálási feloldó

Összetettebb esetekben a DLL-importálások futásidőben történő feloldására is használható SetDllImportResolver . Az alábbi példában a rendszer feloldja, nativedep hogy nativedep_avx2 a processzor támogatja-e.

Tipp.

Ez a funkció csak a .NET Core 3.1-ben és a .NET 5+-ban érhető el.

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace PInvokeSamples
{
    public static partial class Program
    {
        [LibraryImport("nativedep")]
        private static partial 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;
        }
    }
}

Lásd még