Delen via


Systeemeigen bibliotheek laden

In dit artikel wordt uitgelegd welke paden de runtime doorzoekt bij het laden van systeemeigen bibliotheken via P/Invoke. Het laat ook zien hoe u deze kunt gebruiken SetDllImportResolver.

Variaties in bibliotheeknamen

Om eenvoudiger platformoverschrijdende P/Invoke-code te vergemakkelijken, voegt de runtime de canonieke gedeelde bibliotheekextensie (.dll.soof .dylib) toe aan systeemeigen bibliotheeknamen. Op Unix-platforms probeert de runtime ook vooraf libte gaan. Deze variaties in bibliotheeknamen worden automatisch doorzocht wanneer u API's gebruikt die systeemeigen bibliotheken laden, zoals DllImportAttribute.

Notitie

Absolute paden in bibliotheeknamen (bijvoorbeeld /usr/lib/libc.so) worden als zodanig behandeld en er worden geen variaties doorzocht.

Bekijk het volgende voorbeeld van het gebruik van P/Invoke:

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

Wanneer de DLL wordt uitgevoerd in Windows, wordt in de volgende volgorde gezocht naar:

  1. nativedep
  2. nativedep.dll (als de bibliotheeknaam nog niet eindigt op .dll of .exe)

Bij uitvoering in Linux of macOS probeert de runtime de canonieke gedeelde bibliotheekextensie vooraf lib te geven en toe te voegen. Op deze besturingssystemen worden variaties van bibliotheeknamen in de volgende volgorde geprobeerd:

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

In Linux is de zoekvolgorde anders als de naam van de bibliotheek eindigt op .so of bevat .so. (let op de volgvolgorde .). Kijk een naar het volgende voorbeeld:

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

In dit geval worden de variaties van de bibliotheeknaam in de volgende volgorde geprobeerd:

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

1 Pad wordt alleen gecontroleerd als de bibliotheeknaam geen adreslijstscheidingsteken (/) bevat.

Aangepaste import-resolver

In complexere scenario's kunt SetDllImportResolver u DLL-importbewerkingen tijdens runtime oplossen. In het volgende voorbeeld nativedep wordt omgezet in nativedep_avx2 of de CPU dit ondersteunt.

Tip

Deze functionaliteit is alleen beschikbaar in .NET Core 3.1 en .NET 5+.

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;
        }
    }
}

Zie ook