原生代碼互操作技術允許您從受控代碼訪問非受控庫,或向非受控代碼公開受控庫(反向操作)。
雖然原生程式代碼 Interop 在原生 AOT 和非 AOT 部署中的運作方式類似,但在發佈為原生 AOT 時,有些細節不同。
直接 P/Invoke 呼叫
AOT 編譯的二進位檔中的 P/Invoke 呼叫預設在執行時被懶散綁定,以提升相容性。 您可以設定 AOT 編譯器,以便為由作業系統附帶的動態載入器在系統啟動期間繫結的特定 P/Invoke 方法產生直接呼叫。 透過直接呼叫所參考的非管理函式庫與入口點必須在執行時始終可用,否則原生二進位檔無法啟動。
直接 P/Invoke 呼叫的優點如下:
- 它們具有 較好的穩定狀態效能。
- 它們使得靜態地連結未管理的相依性成為可能。
您可以使用專案檔中的 <DirectPInvoke> 項目來設定直接 P/Invoke 生成。 專案名稱可以是 <modulename>,可啟用模組中所有進入點的直接呼叫,或是 <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 平台上,原生 AOT 使用一份預先填入的直接 P/Invoke 方法清單,該清單包含所有支援的 Windows 版本中可用的方法。
警告
由於直接 P/Invoke 方法是由作業系統動態載入器解析,而不是由原生 AOT 執行時間庫解析,因此直接 P/Invoke 方法不會遵守 DefaultDllImportSearchPathsAttribute。 程式庫搜尋順序會遵循作業系統所定義的動態載入器規則。 某些作系統和載入器提供透過連結器旗標控制動態載入的方法(例如 /DEPENDENTLOADFLAG 在 Windows 或 -rpath Linux 上)。 如需如何指定連結器旗標的詳細資訊,請參閱 連結 一節。
連結
若要以靜態方式連結至非受控程式庫,您必須指定 <NativeLibrary Include="filename" /> 指向 Windows 上的 .lib 檔案,以及在類似 Unix 系統上的 .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 屬性的方法註解為公用 C 入口點並匯出。 這可讓您以動態或靜態方式將 AOT 編譯的模組連結至外部程式。 只有標記UnmanagedCallersOnly的那些方法會在已發佈的組件中被考慮。 不會匯出項目參考或 NuGet 套件中的方法。
如需詳細資訊,請參閱 NativeLibrary 範例。