知識マップ: C# Native AOT DLLをC/C++から呼び出す方法

記事「C# Native AOT DLLをC/C++から呼び出す方法」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。

C#のNative AOTはUnmanagedCallersOnly属性を付けたメソッドをCのエントリポイントとして公開でき、既存のC/C++アプリからin-processでC#のロジックだけを呼び出せる構成を実現する。ただし境界に出せるのはblittableな型に限られるため、実務ではstringやList<T>を直接見せずcreate/destroy/operateのようなハンドルベースのC APIに落とし、呼び出し規約を明示し、例外の代わりにstatus codeでエラーを表現する設計が推奨される。この構成はC/C++がC#ロジックを呼ぶ向きに適する一方、C#からCを呼ぶならP/Invoke、C#からC++を自然に扱うならC++/CLI、32bit/64bitやプロセス境界を越えたい場合やアンロードしたい場合はCOM/IPCの方が向く。ハンドルの採番を32bit幅で使い回すと一周時に無関係なインスタンスを指す危険があり、世代番号の埋め込みが対策になる。

Native AOTでC#をネイティブDLLとしてC/C++から呼ぶ知識マップNative AOTとUnmanagedCallersOnlyでC#をC/C++から呼ばれるネイティブDLLとして発行できること、境界面をC ABIに落とすための呼び出し規約・blittable型・ハンドル設計・エラー表現の要点、P/Invoke・C++/CLI・COMとの使い分けを示す図利用する前提とするで構成できる利用する前提とする前提とする前提とする推奨される対応推奨される対応推奨される対応推奨される対応用いるのは非推奨用いるのは非推奨推奨される対応推奨される対応原因になり得る防止するで確認できる前提とする用いるのは非推奨用いるのは非推奨原因になり得るNative AOTUnmanagedCallersOnly属性blittable型呼び出し規約(calling convention)C ABI(Application Binary Interface)Native AOT publish用のネイティブツールチェーン.NET(Core以降)C/C++からC#ロジックをin-processで呼ぶ要件P/InvokeC#からCの関数群を呼ぶ要件C++/CLIC#からC++ライブラリを自然に扱う要件COM(Component Object Model)32bit/64bitまたはプロセス境界を越える要件プラグインを後でアンロードしたい要件エラーをstatus codeで返す設計ハンドルベースのC API設計(create/destroy/operate)ハンドル採番カウンターのオーバーフローハンドル一周による衝突世代番号を埋め込んだハンドル設計dumpbinインポートライブラリ(.lib)

概念間の関係(全22件)

図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。

主要概念の定義

Native AOT
.NETアプリを単一のネイティブバイナリへ事前コンパイルする発行方式。非対応リストにC++/CLIが明記されている。
UnmanagedCallersOnly属性
static メソッドに付与すると、そのメソッドをネイティブコードから直接呼び出せるCのエントリポイントとして公開できる.NETの属性。
呼び出し規約(calling convention)
関数呼び出しで引数をレジスタとスタックのどちらでどう渡すか、戻り値をどこに置くか、呼び出し後にスタックを戻すのが呼ぶ側か呼ばれる側かを定める約束。
C ABI(Application Binary Interface)
コンパイル済みのバイナリ同士が実行時にどう噛み合うかを、呼び出し規約・型のレイアウト・名前とリンクという3つの約束で定める、機械語レベルの取り決め。
P/Invoke
C#などの.NETコードからアンマネージドなC関数群を呼び出すための、.NETの標準的な相互運用機構。
C++/CLI
ネイティブC++とマネージド.NETの両方を1つのプロジェクトで扱えるMicrosoftの言語拡張。ネイティブDLLとC#の間に薄いラッパー層を作るのに使われる。
COM(Component Object Model)
プロセス内外・言語をまたいでオブジェクトを利用可能にするMicrosoftのバイナリ相互運用規格で、32bit/64bitやプロセス境界を越える橋渡しにも使われる。
エラーをstatus codeで返す設計
ネイティブ境界を越える関数の戻り値をエラーコードとし、実データはoutバッファやポインタ引数で返す、managed例外を境界に漏らさないための設計方針。
ハンドルベースのC API設計(create/destroy/operate)
ネイティブ側にはintptr_t相当のハンドルだけを見せ、状態本体は.NET側で保持しながらcreate/add/get/destroyのようなフラットな関数に分解するAPI設計パターン。
ハンドル採番カウンターのオーバーフロー
long型の採番カウンターをnint(32bitビルドでは32bit幅)へキャストする際に上位ビットが黙って捨てられ、採番が2^32を超えると値が一周する現象。
世代番号を埋め込んだハンドル設計
ハンドルの下位ビットを連番、上位ビットを世代番号とし、destroyのたびに世代を進めることで、同じ連番が巡ってきても値が一致しないようにするハンドル設計。
インポートライブラリ(.lib)
DLLの関数を実行時のLoadLibrary/GetProcAddressを介さず、リンク時に静的に解決できるようにするための.libファイル。

機械可読データ

このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。