다음을 통해 공유


네이티브 AOT와의 네이티브 코드 상호 운용성

네이티브 코드 상호 운용성은 관리 코드에서 비관리 라이브러리에 액세스하거나, 반대로 비관리 코드에서 관리 라이브러리에 액세스할 수 있도록 하는 기술입니다.

네이티브 코드 interop은 네이티브 AOT 및 비 AOT 배포에서 유사하게 작동하지만 네이티브 AOT로 게시할 때는 몇 가지 세부 사항이 다릅니다.

직접 P/Invoke 호출

AOT 컴파일 이진 파일의 P/Invoke 호출은 기본적으로 호환성을 높이기 위해 런타임 시 지연 바인딩됩니다. 운영 체제와 함께 제공되는 동적 로더에 의해 시작 중에 바인딩된 선택한 P/Invoke 메서드에 대한 직접 호출을 생성하도록 AOT 컴파일러를 구성할 수 있습니다. 직접 호출을 통해 참조되는 관리되지 않는 라이브러리와 진입점은 런타임에 항상 사용할 수 있어야 합니다. 그렇지 않으면 네이티브 바이너리가 시작되지 않습니다.

직접 P/Invoke 호출의 이점은 다음과 같습니다.

  • 그들은 더 나은 안정적인 상태 성능을 가지고있다.
  • 관리되지 않는 종속성을 정적으로 연결할 수 있습니다.

프로젝트 파일의 항목을 사용하여 <DirectPInvoke> 직접 P/Invoke 생성을 구성할 수 있습니다. 항목 이름은 모듈의< 모든 진입점에 대해 직접 호출할 수 있는 모듈 이름 또는 특정 모듈 및 진입점에 대해서만 직접 호출할 수 있는 modulename!entrypointname일 수> 있습니다.<>

외부 파일의 진입점 목록을 지정하려면 프로젝트 파일의 항목을 사용합니다 <DirectPInvokeList> . 목록은 직접 P/Invoke 호출 수가 많고 개별 <DirectPInvoke> 항목을 사용하여 지정하는 것은 실용적이지 않은 경우에 유용합니다. 파일에는 빈 줄과 #로 시작되는 주석을 포함할 수 있습니다.

예제:

<ItemGroup>
  <!-- Generate direct PInvoke calls for everything in __Internal -->
  <!-- This option replicates Mono AOT behavior that generates direct PInvoke calls for __Internal -->
  <DirectPInvoke Include="__Internal" />
  <!-- Generate direct PInvoke calls for everything in libc (also matches libc.so on Linux or libc.dylib on macOS) -->
  <DirectPInvoke Include="libc" />
  <!-- Generate direct PInvoke calls for Sleep in kernel32 (also matches kernel32.dll on Windows) -->
  <DirectPInvoke Include="kernel32!Sleep" />
  <!-- Generate direct PInvoke for all APIs listed in DirectXAPIs.txt -->
  <DirectPInvokeList Include="DirectXAPIs.txt" />
</ItemGroup>

Windows에서 Native AOT는 지원되는 모든 Windows 버전에서 사용할 수 있는 직접 P/Invoke 메서드의 미리 채워진 목록을 사용합니다.

경고

직접 P/Invoke 메서드는 네이티브 AOT 런타임 라이브러리가 아닌 운영 체제 동적 로더에 의해 확인되기 때문에 DefaultDllImportSearchPathsAttribute을(를) 준수하지 않습니다. 라이브러리 검색 순서는 운영 체제에서 정의한 동적 로더 규칙을 따릅니다. 일부 운영 체제 및 로더는 링커 플래그(예: /DEPENDENTLOADFLAG Windows 또는 -rpath Linux)를 통해 동적 로드를 제어하는 방법을 제공합니다. 링커 플래그를 지정하는 방법에 대한 자세한 내용은 링크 섹션을 참조하세요.

연결하기

관리되지 않는 라이브러리에 대해 정적으로 연결하려면, Windows에서는 <NativeLibrary Include="filename" /> 파일을 가리키고 Unix와 유사한 시스템에서는 .lib 파일을 가리키도록 .a을 지정해야 합니다.

예제:

<ItemGroup>
  <!-- Generate direct PInvokes for Dependency -->
  <DirectPInvoke Include="Dependency" />
  <!-- Specify library to link against -->
  <NativeLibrary Include="Dependency.lib" Condition="$(RuntimeIdentifier.StartsWith('win'))" />
  <NativeLibrary Include="Dependency.a" Condition="!$(RuntimeIdentifier.StartsWith('win'))" />
</ItemGroup>

네이티브 링커에 추가 플래그를 지정하려면 항목을 사용합니다 <LinkerArg> .

예제:

<ItemGroup>
  <!-- link.exe is used as the linker on Windows -->
  <LinkerArg Include="/DEPENDENTLOADFLAG:0x800" Condition="$(RuntimeIdentifier.StartsWith('win'))" />

  <!-- Native AOT invokes clang/gcc as the linker, so arguments need to be prefixed with "-Wl," -->
  <LinkerArg Include="-Wl,-rpath,'/bin/'" Condition="$(RuntimeIdentifier.StartsWith('linux'))" />
</ItemGroup>

네이티브 내보내기

네이티브 AOT 컴파일러는 비어 있지 않은 UnmanagedCallersOnlyAttribute 프로퍼티가 포함된 EntryPoint으로 주석이 추가된 메소드를 공용 C 엔트리 포인트로 내보냅니다. 이렇게 하면 AOT 컴파일된 모듈을 동적으로 또는 정적으로 외부 프로그램에 연결할 수 있습니다. 게시된 어셈블리에 표시된 UnmanagedCallersOnly 메서드만 고려됩니다. 프로젝트 참조 또는 NuGet 패키지의 메서드는 내보내지지 않습니다. 자세한 내용은 NativeLibrary 샘플을 참조하세요.