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
.so
of .dylib
) toe aan systeemeigen bibliotheeknamen. Op Unix-platforms probeert de runtime ook vooraf lib
te 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:
nativedep
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:
nativedep.so
/nativedep.dylib
libnativedep.so
/libnativedep.dylib
1nativedep
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:
nativedep.so.6
libnativedep.so.6
1nativedep.so.6.so
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;
}
}
}