네이티브 라이브러리 로딩
이 문서에서는 P/Invoke를 통해 네이티브 라이브러리를 로드할 때 런타임이 검색하는 경로를 설명합니다. 또한 SetDllImportResolver를 사용하는 방법을 보여 줍니다.
라이브러리 이름 변형
더 간단한 플랫폼 간 P/Invoke 코드를 용이하게 하기 위해 런타임은 정식 공유 라이브러리 확장(.dll
, .so
또는 .dylib
)을 네이티브 라이브러리 이름에 추가합니다. Unix 기반 플랫폼에서는 런타임이 앞에 lib
를 추가하려고 시도합니다. 이러한 라이브러리 이름 변형은 DllImportAttribute와 같은 네이티브 라이브러리를 로드하는 API를 사용할 때 자동으로 검색됩니다.
참고 항목
라이브러리 이름(예: /usr/lib/libc.so
)의 절대 경로는 있는 그대로 처리되며 변형은 검색되지 않습니다.
P/Invoke를 사용하는 다음 예를 고려합니다.
[DllImport("nativedep")]
static extern int ExportedFunction();
Windows에서 실행하는 경우 DLL은 다음 순서로 검색됩니다.
nativedep
nativedep.dll
(라이브러리 이름이 아직.dll
또는 .exe
로 끝나지 않은 경우)
Linux 또는 macOS에서 실행되는 경우 런타임은 lib
앞에 정식 공유 라이브러리 확장을 추가하려고 시도합니다. 이러한 OS에서는 라이브러리 이름이 다음 순서로 변형됩니다.
nativedep.so
/nativedep.dylib
libnativedep.so
/libnativedep.dylib
1nativedep
libnativedep
1
Linux에서는 라이브러리 이름이 .so
로 끝나거나 .so.
를 포함하는 경우 검색 순서가 다릅니다(후행 .
참고). 다음 예제를 참조하세요.
[DllImport("nativedep.so.6")]
static extern int ExportedFunction();
이 경우 라이브러리 이름은 다음 순서로 변형됩니다.
nativedep.so.6
libnativedep.so.6
1nativedep.so.6.so
libnativedep.so.6.so
1
1 라이브러리 이름에 디렉터리 구분 문자(/
)가 포함되지 않은 경우에만 경로가 확인됩니다.
사용자 지정 가져오기 해결 프로그램
더 복잡한 시나리오에서는 SetDllImportResolver를 사용하여 런타임에 DLL 가져오기를 해결할 수 있습니다. 다음 예에서는 CPU가 지원하는 경우 nativedep
가 nativedep_avx2
로 확인됩니다.
팁
이 기능은 .NET Core 3.1 및 .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;
}
}
}
참고 항목
.NET