従来、私は MFC 拡張 dll を使用し、dllimport/dllexport を使用してインポート/エクスポートを行ってきました。
ただし、dll が /clr を使用するように変更された場合、このメソッドはコストが高くなります。これは、呼び出しによってダブルサンクが発生する可能性があるためです。現在、パフォーマンスが大幅に低下しており、ダブル サンクを停止する必要があります。私が説明した解決策は、すべてが __clrcall 規則を使用していることを確認することを提案していますが、これは dllexport では機能しません。
ダブルサンキングに関するマイクロソフト独自のセクションでは、次のように提案されています。
同様に、マネージ関数をエクスポート (dllexport、dllimport) すると、ネイティブ エントリ ポイントが生成され、その関数をインポートして呼び出す関数はすべて、ネイティブ エントリ ポイントを介して呼び出されます。このような状況でダブル サンクを回避するには、ネイティブのエクスポート/インポート セマンティクスを使用しないでください。#using を介してメタデータを参照するだけです (#using ディレクティブ (C++) を参照)。
私にとって、これは、自分のクラスから dllexport/dllimport を削除して、stdafx.h に #using を貼り付けることができるかのように見えます。ただし、ネイティブ型の場合、これは LNK2028 (未解決のトークン) および LNK2019 (未解決の外部シンボル) になります。リンカーに .lib を含めるかどうかに違いはありません。私はまだこのエラーが発生します。
それで、私の質問は、ダブルサンクを回避し、C++/CLI ライブラリからネイティブ型をインポートする最善の方法は?
よろしく
ニック
** アップデート **
テストからのいくつかの更新。
dll が /clr でコンパイルされるとすぐに、(dllexport/dllimport を使用して) ネイティブ型に対してダブル サンクが発生します。
これは、ファイルごとに CLR サポートをオフにすることで軽減できます。これは面倒で、ネイティブ型が clr を使用することがあるため、どこでも実行できるわけではありません。また、呼び出し先もネイティブにコンパイルして動作させる必要があります。
メソッドに __clrcall のマークを付けることができますが、dllexport と混合するとコンパイル エラーが発生します。ただし、ダブルサンクなしで次のコードを機能させることができました。
// MFCCLRLIB_API is defined in the library only (as dllexport) // but NOT defined when using (dllimport) // MFCCLRLIB_CALL is defined as empty in the library, // but __clrcall when using. #ifndef _MFCCLRLIB #define MFCCLRLIB_API #define MFCCLRLIB_CALL __clrcall #endif class MFCCLRLIB_API ThunkHack { public: ThunkHack(); ThunkHack(const ThunkHack&); ~ThunkHack(); }; class MFCCLRLIB_API ThunkHackCaller { public: ThunkHackCaller(void); ~ThunkHackCaller(void); virtual void MFCCLRLIB_CALL UseThunkClass(ThunkHack thunk); };
これはコンパイルされ、ライブラリの外部から呼び出し元クラスを使用できるようになり、ダブルサンクは発生しません。それが私が欲しいものです。しかし、私はこれがその方法ではないことを懸念しています。このアプローチが安全であることを示唆するものは読んだことがありません。
私たちが見ているようなパフォーマンスの低下を避けるために、混合モードの C++ ライブラリを効率的に使用する方法についてのガイドラインが本当に欲しいです。
-ニック