Sdílet prostřednictvím


Spolupráce nativního kódu s nativní AOT

Nativní interoperabilita kódu je technologie, která umožňuje přístup k nespravovaným knihovnám ze spravovaného kódu nebo zpřístupnění spravovaných knihoven nespravovanému kódu (opačným směrem).

I když nativní interoperabilita kódu funguje podobně v nativních nasazeních AOT a jiných než AOT, při publikování jako nativní AOT existují určité specifika.

Přímé volání P/Invoke

Volání P/Invoke v binárních souborech kompilovaných AOT jsou ve výchozím nastavení svázána lazily za běhu, aby byla lépe kompatibilita. Kompilátor AOT můžete nakonfigurovat tak, aby vygeneroval přímá volání vybraných metod P/Invoke, které jsou vázané při spuštění dynamickým zavaděčem, který je součástí operačního systému. Nespravované knihovny a vstupní body odkazované prostřednictvím přímých volání musí být vždy dostupné za běhu, jinak se nativní binární soubor nespustí.

Výhody přímých volání P/Invoke jsou:

  • Mají lepší výkon stabilního stavu.
  • Umožňují propojit nespravované závislosti staticky.

Přímé generování P/Invoke můžete nakonfigurovat pomocí <DirectPInvoke> položek v souboru projektu. Název položky může být <buď název> modulu, který umožňuje přímé volání pro všechny vstupní body v modulu nebo <název!entrypointname> modulu, což umožňuje přímé volání pouze pro konkrétní modul a vstupní bod.

Chcete-li zadat seznam vstupních bodů v externím souboru, použijte <DirectPInvokeList> položky v souboru projektu. Seznam je užitečný v případech, kdy je počet přímých volání P/Invoke velký a není praktické je specifikovat pomocí jednotlivých položek <DirectPInvoke>. Soubor může obsahovat prázdné řádky a komentáře začínající na #.

Příklady:

<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>

Nativní funkce AOT ve Windows používá předem vyplněný seznam přímých metod P/Invoke, které jsou k dispozici ve všech podporovaných verzích Windows.

Výstraha

Vzhledem k tomu, že přímé metody P/Invoke jsou vyřešeny dynamickým zavaděčem operačního systému, a ne nativní knihovnou modulu runtime AOT, přímé metody P/Invoke nerespektují DefaultDllImportSearchPathsAttribute. Pořadí vyhledávání knihovny se bude řídit pravidly dynamického zavaděče, jak jsou definována operačním systémem. Některé operační systémy a zavaděče nabízejí způsoby řízení dynamického načítání prostřednictvím příznaků linkeru (například /DEPENDENTLOADFLAG ve Windows nebo -rpath v Linuxu). Další informace o tom, jak určit příznaky linkeru, najdete v části Propojení .

Propojování

Pokud chcete staticky propojit s nespravovanou knihovnou, musíte zadat <NativeLibrary Include="filename" /> odkazování na .lib soubor ve Windows a .a soubor v systémech Unix.

Příklady:

<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>

Pokud chcete pro nativní linker zadat další příznaky, použijte položku <LinkerArg>.

Příklady:

<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>

Nativní exporty

Nativní kompilátor AOT exportuje metody s neprázdnou vlastností UnmanagedCallersOnlyAttribute anotované EntryPoint jako veřejné vstupní body v jazyce C. To umožňuje dynamicky nebo staticky propojit kompilované moduly AOT do externích programů. Zvažují se pouze metody označené UnmanagedCallersOnly v publikovaném sestavení. Metody v odkazech projektu nebo balíčcích NuGet se neexportují. Další informace naleznete v ukázce NativeLibrary.