In your C# code, declare your native C++ method with the DLLImport attribute, and call this method from your BackgroundWorker.ProgressChanged
handler.
DISCLAIMER: I have not tested any of this code, and this may not be the best approach, but at least in theory I think this would work. Hopefully one of the more experienced members here can verify if this is actually correct.
This assumes you are starting the background worker from C#, and you want the ProgressChanged
event in C# (I assume this is the case since your UI is in C#).
You can still use the BackgroundWorker
in C#, but just have it call your native method using the DLLImport I mentioned above. You can also modify the signature of your method to take a function pointer that matches the signature for ReportProgress
, and then call that delegate from your native code.
MSDN has some articles on Marshalling delegates and function pointers(although the examples all use C++/CLI). You may also want to look at the documentation for the DLLImport and MarshalAs attributes, and the UnmanagedType enum.
For instance, if your native method was
void foo(int arg1, BOOL arg2)
{
// Your code here
}
you would define a function pointer type in your native code as
// Corresponds to void BackgroundWorker.ReportProgress(int progress, object state)
typedef void (*NativeReportProgress) (int, void*);
and change your native signature to
void foo(int arg1, BOOL arg2, NativeReportProgress progressPtr)
{
// Some code.
progressPtr(progressValue, stateVar);
}
Your DLLImport
for foo
would look like
// 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);
Then your worker would look like
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);
}
Hopefully that made some sense (and hopefully it's right, too!)