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 hledá při načítání nativních knihoven prostřednictvím volání nespravovaného kódu. 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 platformách se systémem Unix bude modul runtime také zkoušet předpending 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 neschybné a nebudou prohledány žádné varianty.
Představte si následující příklad použití volání nespravovaného kódu:
[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 ještě.dllnekončí nebo .exe)
Při spuštění v Linuxu nebo macOS se modul runtime pokusí o předpending lib a připojení 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 (/).
Překladač vlastních importů
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 přeloží nativedep na to, nativedep_avx2 jestli 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;
}
}
}