Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo explica quais caminhos o runtime pesquisa ao carregar bibliotecas nativas por meio de P/Invoke. Este exemplo também mostra como usar SetDllImportResolver.
Variações do nome de biblioteca
Para simplificar o código P/Invoke entre plataformas, o runtime adiciona a extensão de biblioteca compartilhada canônica (.dll, .so ou .dylib) a nomes de biblioteca nativa. Em plataformas baseadas em Unix, o runtime também tentará anexar lib. Essas variações de nomes de biblioteca são pesquisadas automaticamente quando você usa APIs que carregam bibliotecas nativas, como DllImportAttribute.
Observação
Caminhos absolutos em nomes de biblioteca (por exemplo, /usr/lib/libc.so) são tratados como estão e nenhuma variação será pesquisada.
Considere o seguinte exemplo de uso de P/Invoke:
[DllImport("nativedep")]
static extern int ExportedFunction();
Ao executar no Windows, a DLL é pesquisada na seguinte ordem:
nativedep-
nativedep.dll(se o nome da biblioteca já não terminar com.dllou .exe)
Ao ser executado no Linux ou no macOS, o runtime tentará preceder lib e acrescentar a extensão de biblioteca compartilhada canônica. Nesses sistemas operacionais, as variações do nome de biblioteca são tentadas na seguinte ordem:
nativedep.so/nativedep.dylib-
libnativedep.so/libnativedep.dylib1 nativedep-
libnativedep1
No Linux, a ordem de pesquisa será diferente se o nome da biblioteca terminar com .so ou contiver .so. (observe o . à direita). Considere o seguinte exemplo:
[DllImport("nativedep.so.6")]
static extern int ExportedFunction();
Nesse caso, as variações do nome de biblioteca são tentadas na seguinte ordem:
nativedep.so.6-
libnativedep.so.61 nativedep.so.6.so-
libnativedep.so.6.so1
1 O caminho será verificado somente se o nome da biblioteca não contiver um caractere separador de diretório (/).
Resolvedor de importação personalizado
Em cenários mais complexos, você pode usar SetDllImportResolver para resolver as importações de DLL em runtime. No exemplo a seguir, nativedep será resolvido como nativedep_avx2 se a CPU der suporte.
Dica
Essa funcionalidade só está disponível no .NET Core 3.1 e no .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;
}
}
}