C ++ COM C#混合モードインター型
-
20-09-2019 - |
質問
管理されていないC ++からC#ライブラリの実装を呼び出すためのオプションを理解しようとしています。
私のトップレベルモジュールは、管理されていないC ++ COM/ATL DLLです。既存の管理されたC#DLLの機能を統合したいと思います。私は、両方のライブラリのソースを再コンパイルすることができます。
私はような記事を読むことから理解しています この概要 MSDNおよび これはとても質問です ネイティブC ++コードがC#ライブラリを呼び出すことを可能にする「混合モード」DLLを作成できる可能性があること。
このアプローチについていくつか質問があります。
- これをセットアップするにはどうすればよいですか?既存のCOM/ATLプロジェクトの一部のプロパティを変更して、C#モジュールの使用を許可できますか?
- これらの混合モード呼び出しは、COM Interopコールとのパフォーマンスがどのように異なりますか?モジュール間の変換や深いコピーを防ぐために使用できる一般的な文字列形式はありますか?
- このDLLがミックスモードを作成している場合、COMクライアントが同じ方法でインターフェース/使用できますか、それともミックスモードを認識する必要がありますか?
- CLRを含めると、このCOMオブジェクトをロードすると、かなりのオーバーヘッドが課されますか?
私はWindows開発を初めて使用していますので、質問ステートメントの何かが明確化または修正が必要な場合はコメントしてください。
前もって感謝します。
解決
これをセットアップするにはどうすればよいですか?既存のCOM/ATLプロジェクトの一部のプロパティを変更して、C#モジュールの使用を許可できますか?
そのプロジェクトを完全に制御する場合、そのような設定を変更することは問題ではありません。必要なのは有効にすることだけです /clr
このプロジェクトの場合(プロジェクトプロパティでは、「一般」ページを開き、「共通言語ランタイム」サポートを探します)。これで、マネージドハンドルを使用できます(^
)必要に応じて、プロジェクト内の他のC ++/CLIビット。 Plain C ++で記述されたすべての既存のコードは、機能し続ける必要があります(可能な限りMSILにコンパイルされますが、そのセマンティクスは変更されません)。
これらの混合モード呼び出しは、COM Interopコールとのパフォーマンスがどのように異なりますか?モジュール間の変換や深いコピーを防ぐために使用できる一般的な文字列形式はありますか?
混合モードの呼び出しは、より速い呼び出しコンベンションを使用し、COM Interopの方法をマーシャリングしないため、より速くなります(本質的に互換性のあるタイプを使用するか、独自の明示的な変換を行うか)。
一般的な文字列形式はありません - 問題は System::String
どちらもバッファーを割り当てて所有しており、不変であることも必要です。だからあなたは自分でバッファーを作成してからそれを包むことはできません String
, 、または作成します String
次に、テキストを出力するバッファとして使用します。
このDLLがミックスモードを作成している場合、COMクライアントが同じ方法でインターフェース/使用できますか、それともミックスモードを認識する必要がありますか?
同じようにインターフェースすることもできますが、ネイティブのエントリポイントを介して入力された場合、既にロードされていない限り、CLRをプロセスにロードしようとします。呼び出しクライアントが呼び出しの前に既にCLRをロードしていた場合(またはクライアント自体がマネージドコードから呼び出された)、既にロードされているCLRを取得します。これは、コードが必要とするCLRとは異なる場合があります(クライアントなど1.1がロードされている可能性があり、コードが2.0が必要です)。
CLRを含めると、このCOMオブジェクトをロードすると、かなりのオーバーヘッドが課されますか?
それはあなたがオーバーヘッドで定義するものに依存します。コードサイズ?ランタイムペナルティ?メモリフットプリント?
いずれにせよ、CLRをロードすると、すべてのGCおよびJIT機械を取得することがわかります。それらは安くはありません。とはいえ、とにかくマネージドコードを最終的に呼び出す必要がある場合、これを回避する方法はありません - あなたは 持ってる これを行うためにCLRを何らかのプロセスにロードします。ペナルティは、COM Interopと混合モードC ++/CLIアセンブリの間で違いはありません。
他のヒント
私はこのアプローチを積極的に使用したことがないので、たとえば文字列の問題のような詳細について多くを言うことはできません。
ただし、VSウィザードにプロキシを作成するだけで、C#コードから任意のCOMインターフェイスを簡単に消費できます。COMと.NETを呼び出すときに常に持っているものを除いて、パフォーマンスオーバーヘッドはありません。
他の方向には、C#アセンブリを設定する必要があります。 ComVisibleAttribute
Trueに(VSでは、プロジェクトプロパティの単純なチェックボックスです)、コンパイラは自動的にCOMインターフェイスを作成します。繰り返しますが、追加のパフォーマンスペナルティはありません。
hth!