C# コードで、DLLImport 属性を使用してネイティブ C++ メソッドを宣言し、BackgroundWorker.ProgressChanged
ハンドラーからこのメソッドを呼び出します。
免責事項:私はこのコードをテストしていません。これは最善のアプローチではないかもしれませんが、少なくとも理論的にはこれでうまくいくと思います。ここの経験豊富なメンバーの 1 人が、これが実際に正しいかどうかを確認できることを願っています。
これは、C# からバックグラウンド ワーカーを開始していて、C# でProgressChanged
イベントが必要であることを前提としています (UI が C# であるため、これが当てはまると思います)。
は引き続きBackgroundWorker
C# で使用できますが、前述の DLLImport を使用してネイティブ メソッドを呼び出すだけです。メソッドのシグネチャを変更して、 のシグネチャと一致する関数ポインタを受け取り、ReportProgress
ネイティブ コードからそのデリゲートを呼び出すこともできます。
MSDN には、デリゲートと関数ポインターのマーシャリングに関する記事がいくつかあります(ただし、例ではすべて C++/CLI を使用しています)。DLLImport属性とMarshalAs属性、およびUnmanagedType列挙のドキュメントも参照してください。
たとえば、ネイティブ メソッドが
void foo(int arg1, BOOL arg2)
{
// Your code here
}
ネイティブ コードで関数ポインター型を次のように定義します。
// Corresponds to void BackgroundWorker.ReportProgress(int progress, object state)
typedef void (*NativeReportProgress) (int, void*);
ネイティブ署名を次のように変更します
void foo(int arg1, BOOL arg2, NativeReportProgress progressPtr)
{
// Some code.
progressPtr(progressValue, stateVar);
}
あなたDLLImport
の forfoo
は次のようになります
// Delegate type for BackgroundWorker.ReportProgress
delegate void ReportProgressDelegate(int progress, object state);
// The MarshalAs attribute should handle the conversion from the .NET
// delegate to a native C/C++ function pointer.
[DLLImport]
void foo([MarshalAs(UnmanagedType.I4)] Int32 arg1,
[MarshalAs(UnmanagedType.Bool)] bool arg2,
[MarshalAs(UnmanagedType.FunctionPointer)] ReportProgressDelegate progressDel);
次に、ワーカーは次のようになります
void DoWork(object sender, DoWorkEventArgs e)
{
var worker = (BackgroundWorker)sender;
// Notice that worker.ReportProgress is not followed the by ().
// We're not actually calling the method here, we're just passing
// a function pointer to that method into foo.
foo(intArg, boolArg, worker.ReportProgress);
}
うまくいけば、それはある程度の意味をなすものです (そしてうまくいけば、それも正しいです!)