代表和回调 [英] Delegates and Callbacks
问题描述
我昨天看到这个解决方案是针对某人的相同主题的问题发布的.
I saw this solution posted yesterday for someone''s question with same subject.
//defines typedefs to make declarations easier
typedef void (__stdcall *CALLBACK1)(int);
typedef void (__stdcall *CALLBACK2)(bool);
//type of the pointer passed to you callback
struct TIMER_PARAM
{
CALLBACK1 callback1;
CALLBACK2 callback2;
};
void CALLBACK WaitOrTimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
//get your params
TIMER_PARAM* pParam = (TIMER_PARAM*)lpParameter;
if(condition1)
pParam->callback1(10);
if(condition2)
pParam->callback2(true);
}
__declspec(dllexport) void __cdecl StartUpdate(
CALLBACK1 callback1, CALLBACK2 callback2)
{
//this pointer will be passed to your callback
//you will need to delete this pointer somewhere in your code
//to prevent a memory leak
TIMER_PARAM* parameters = new TIMER_PARAM;
parameters->Callback1 = callback1;
parameters->Callback1 = callback2;
/*start the timer here*/
bool success = ::CreateTimerQueueTimer(
&m_timerHandle,
NULL,
TimerFire,
// will be given as an argument to your timer function
parameters,
0,
1000,
WT_EXECUTEINTIMERTHREAD);
}
我想知道如何使用System :: Timers :: Timer在C ++/CLI中做类似的事情.
I am wondering how to do a similar thing in C++/CLI using System::Timers::Timer.
aTimer->Elapsed+= gcnew ElapsedEventHandler(TimerFire);
如何将struct对象传递给
How can I pass the struct object to the
static void TimerFire(Object ^sender, ElapsedEventArgs ^e)
有没有一种方法可以在(Object ^ sender)参数中发送TIMER_PARAM结构对象.
或者因为我的类是托管类,所以有一种更优雅的方法将函数指针从C#传递到托管C ++类.
预先感谢您的帮助.
Is there a way to send TIMER_PARAM struct object in (Object ^sender) parameter.
Or since my class is managed class is there a more elegant way to pass function pointers from C# to managed C++ class.
Thanks in advance for your help.
推荐答案
这不是C#和C ++/CLI之间的界限,只有C ++和C ++/CLI之间的界限.
.NET中没有函数指针"(从OOP的角度来看,它是底层的,并不是真正可靠的概念),只有委托.委托实例是一种结构,其中包含方法的某些代码的入口点的集合,每个入口点都具有实现该方法的类/结构实例的值(与"this"指针在每个实例(非静态)方法中传递的相同;此集合称为调用列表,可以通过System.Delegate.GetInvocationList
显式调用显式的委托实例来显式遍历.仅对于静态方法"this"不使用.静态和实例方法可以在任何调用列表中混合使用. br/>
C#和C ++/CLI语言之间的区别在这里不是必需的:
C ++/CLI:
This is not a boundary between C# and C++/CLI, there is only a boundary between C++ and C++/CLI.
There are no "function pointers" (which is low-level and not really robust concept in view of OOP) in .NET, there are only delegates. A delegate instance is a structure with includes the collection of entry points of some code of a methods, each with the value of the class/structure instance implementing the method (same as "this" pointers passes in every instance (non-static) method; this collection is called invocation list and can be traversed explicitly via invocation of the delegate instance of explicitly throughSystem.Delegate.GetInvocationList
. Only for a static method "this" is not used. Static and instance methods can mix up in any invocation list.
Difference between C# and C++/CLI languages is not essential here:
C++/CLI:
aTimer->Elapsed += gcnew ElapsedEventHandler(TimerFire);
//...
// this is no point to use static here (surprize!),
// with static, you loose access to the instance (via "this"), so write non-static.
void TimerFire(Object ^sender, ElapsedEventArgs ^e) { /*...*/ }
C#:
C#:
void TimerFire(Object sender, ElapsedEventArgs e) { /* ... */ }
//...
aTimer->Elapsed += new TimerFire;
//same as:
aTimer2->Elapsed += new ElapsedEventHandler(TimerFire);
//even better
aTimer3->Elapsed += delegate(object sender, ElapsedEventArgs eventArgs) {
//TimerFire is not needed, call any code here,
//it may or may not use sender and eventArgs
};
//the most convenient way is using lambda:
aTimer4->Elapsed += (sender, eventArgs) => {
//TimerFire is not needed, call any code here,
//it may or may not use sender and eventArgs
//you don't even need to argument types:
//they are inferred from even type (so called type inference)
};
您可以以任何组合使用这些声明:在C#上编写实现,然后以C ++/CLI或相反的方式添加到调用列表中.
最后的通知:绝对避免使用计时器.请改用线程!
You can use these declarations in any combination: write implementation on C# and add to the invocation list in C++/CLI or the other way around.
A final notice: avoid using timers by all means. Use threads instead!
这篇关于代表和回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!