Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek vysvětluje, které cesty modul runtime prohledává při načítání nativních knihoven prostřednictvím P/Invoke. Také ukazuje, jak používat SetDllImportResolver.
Varianty názvů knihoven
Pro usnadnění jednoduššího kódu P/Invoke pro různé platformy modul runtime přidá do názvů nativních knihoven kanonické rozšíření sdílené knihovny (.dll.sonebo.dylib). Na unixových platformách se běhové prostředí také pokusí o předřazení lib. Tyto varianty názvů knihoven se automaticky prohledávají při použití rozhraní API, která načítají nativní knihovny, například DllImportAttribute.
Poznámka:
Absolutní cesty v názvech knihoven (například /usr/lib/libc.so) se považují za dané a nebudou hledány žádné varianty.
Zvažte následující příklad použití P/Invoke:
[DllImport("nativedep")]
static extern int ExportedFunction();
Při spuštění ve Windows se knihovna DLL vyhledá v následujícím pořadí:
nativedep-
nativedep.dll(pokud název knihovny nekončí na.dllnebo na .exe)
Při spuštění v Linuxu nebo macOS se runtime pokusí o předřazení lib a přidání kanonického rozšíření sdílené knihovny. V těchto operačních systémech se varianty názvů knihoven zkouší v následujícím pořadí:
nativedep.so/nativedep.dylib-
libnativedep.so/libnativedep.dylib1 nativedep-
libnativedep1
V Linuxu se pořadí hledání liší, pokud název knihovny končí .so nebo obsahuje .so. (všimněte si koncového .). Představte si následující příklad:
[DllImport("nativedep.so.6")]
static extern int ExportedFunction();
V tomto případě se varianty názvů knihoven zkouší v následujícím pořadí:
nativedep.so.6-
libnativedep.so.61 nativedep.so.6.so-
libnativedep.so.6.so1
1 Cesta je zaškrtnutá pouze v případě, že název knihovny neobsahuje znak oddělovače adresáře (/).
Vlastní importní resolver
Ve složitějších scénářích můžete použít SetDllImportResolver k řešení importů DLL v běhu programu. V následujícím příkladu se nativedep změní na nativedep_avx2, pokud ho procesor podporuje.
Návod
Tato funkce je dostupná pouze v .NET Core 3.1 a .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;
}
}
}