[英]operate with loop in unmanaged c++ dll from c#(callbacks)
I have written an unmanaged c++ dll that works good (IPinvoke))) There is one resource-consuming function in it - there is a loop with complex time consuming logic. 我已经编写了一个运行良好的非托管c ++ dll(IPinvoke)))其中有一个资源消耗函数-存在一个循环,其中包含复杂的耗时逻辑。 What is the best way to calculate percentage of this loop progress and sending break to this loop - using callbacks or may be passing parameters?
计算此循环进度百分比并向该循环发送中断的最佳方法是什么-使用回调或可能传递参数? If callbacks is the most good variant - could anyone provide sample?
如果回调是最好的变体-有人可以提供示例吗?
in dll: 在dll中:
extern "C" _declspec(dllexport) uint8* resourceConsumingFunction(uint8* dataBufer)
{
//there is a loop with many math here
return dataBuffer;
}
in c# 在C#中
[DllImport("MyLib.DLL", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern byte* resourceConsumingFunction(byte* dataBuf);
//.....
byte* bufbuf = resourceConsumingFunction(data);//there I need to break this function and to get //percentage
Sure, a callback can work. 当然,回调可以工作。 You'll need a function pointer in the C++ code, something like this:
您将在C ++代码中需要一个函数指针,如下所示:
typedef void (__stdcall * pfnCallback)(int progress, int* cancel);
extern "C" _declspec(dllexport)
uint8* resourceConsumingFunction(uint8* dataBuffer, pfnCallback callback)
{
for (int progress = 0;;) {
int cancel = 0;
callback(progress, &cancel);
if (cancel) return null;
// More code
//...
}
return dataBuffer;
}
And the equivalent C# code would be: 等效的C#代码为:
private void delegate pfnCallback(int progress, out bool cancel);
private void makeCall() {
var callback = new pfnCallback(showProgress);
var bufptr = resourceConsumingFunction(somebuf, callback);
GC.KeepAlive(callback);
// etc...
}
private void showProgress(int progress, out bool cancel) {
// etc...
}
Using __stdcall for the callback helps keep the delegate declaration simple. 对回调使用__stdcall有助于简化委托声明。 The GC.KeepAlive() call is necessary to stop the garbage collector from collecting the delegate object too soon.
必须使用GC.KeepAlive()来阻止垃圾回收器过早地收集委托对象。
Based on the info you provided, I think you'll have to rewrite your dll from scratch. 根据您提供的信息,我认为您必须从头开始重写dll。
I'd make it a BackgroundWorker, like this (pseudocode, look it up on MSDN): 我将其设置为BackgroundWorker,如下所示(伪代码,在MSDN上查找):
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (s,e) =>
{
loop(loopcondition)
{
... math magic, in which you also calculate percentage ...
worker.ReportProgress(percentage); // fire 'ProgressChanged' event handled below
}
};
worker.ProgressChanged += (s,e) => { /*e.ProgressPercentage is the value you passed, here you handle it*/ };
//WARNING: i don't remember the exact event name right now, look it up!
worker.WorkerCompleted += (s,e) => { /*when job is done, you can do something here*/ };
you can interact with UI in the ProgressChanged
and WorkerCompleted
events, not in DoWork
(it's being run in a separate thread). 您可以在
ProgressChanged
和WorkerCompleted
事件中与UI进行交互,而不是在DoWork
进行交互(它在单独的线程中运行)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.