4

これを技術的に機能させることができることはわかっていますが、可能な限りクリーンなソリューションを実装したいと考えています。状況は次のとおりです。

アンマネージ C スタイル ライブラリをラップするマネージ ライブラリがあります。私が現在ラップしている C スタイルのライブラリ機能は、文字列のリストを含むいくつかの処理を行います。ライブラリのクライアント コードはデリゲートを提供できます。リストの処理中に「無効な」シナリオが発生した場合、ライブラリはこのデリゲートを介してクライアントにコールバックし、クライアントが使用する戦略を選択できるようにします (例外をスローし、無効な文字など)

私が理想的に望んでいるのは、すべてのマネージ C++ を 1 つの関数に分離してから、アンマネージ パラメーターのみを受け取る別の関数を呼び出して、すべてのネイティブ C++ とアンマネージ コードをその時点で分離できるようにすることです。このアンマネージ コードにコールバック メカニズムを提供することは、私にとって難点であることがわかっています。


#pragma managed
public delegate string InvalidStringFilter(int lineNumber, string text);
...
public IList<Result> DoListProcessing(IList<string> listToProcess, InvalidStringFilter filter)
{
  // Managed code goes here, translate parameters etc.
}

#pragma unmanaged
// This should be the only function that actually touches the C-library directly
std::vector<NativeResult> ProcessList(std::vector<char*> list, ?? callback);

このスニペットでは、すべての C ライブラリ アクセスを ProcessList 内に保持したいのですが、処理中にコールバックを実行する必要があります。このコールバックは、一部のクライアントから渡される InvalidStringFilter デリゲートの形式で提供されます。私の管理ライブラリ。

4

3 に答える 3

2

.NET は、適切に宣言されている場合、デリゲートを関数へのポインターに自動変換できます。2つの注意点があります

  1. C 関数は STDCALL でビルドする必要があります
  2. 関数へのポインターはオブジェクトへの参照としてカウントされないため、基になるオブジェクトがガベージ コレクションされないように、参照が保持されるように調整する必要があります。

http://www.codeproject.com/KB/mcpp/FuncPtrDelegate.aspx?display=Print

于 2008-10-03T19:50:49.627 に答える
2

問題を正しく理解している場合は、C ライブラリとマネージ デリゲートの間のブリッジとして機能する C++/CLI アセンブリで、アンマネージ コールバック関数を宣言する必要があります。


#pragma managed
public delegate string InvalidStringFilter(int lineNumber, string text);

...
static InvalidStringFilter sFilter;

public IList<Result> DoListProcessing(IList<string> listToProcess, InvalidStringFilter filter)
{
  // Managed code goes here, translate parameters etc.
  SFilter = filter;
}

#pragma unmanaged

void StringCallback(???)
{
  sFilter(????);
}

// This should be the only function that actually touches the C-library directly
std::vector<NativeResult> ProcessList(std::vector<char*> list, StringCallback);

書かれているように、このコードは明らかにスレッドセーフではありません。スレッド セーフが必要な場合は、コールバックで正しいマネージド デリゲート (ThreadStatic) を検索するために他のメカニズムが必要になるか、使用できるユーザー提供の変数がコールバックに渡される可能性があります。

于 2008-10-03T19:52:15.707 に答える
0

あなたはこのようなことをしたい:

typedef void (__stdcall *w_InvalidStringFilter) (int lineNumber, string message);

GCHandle handle = GCHandle::Alloc(InvalidStringFilter);
w_InvalidStringFilter callback = 
  static_cast<w_InvalidStringFilter>(
    Marshal::GetFunctionPointerForDelegate(InvalidStringFilter).ToPointer()
  );

std::vector<NativeResult> res = ProcessList(list, callback);
于 2008-11-03T12:18:12.120 に答える