Click here to Skip to main content
15,923,006 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
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);
}
I am wondering how to do a similar thing in C++/CLI using System::Timers::Timer.

aTimer->Elapsed+= gcnew ElapsedEventHandler(TimerFire);

How can I pass the struct object to the
static void TimerFire(Object ^sender, ElapsedEventArgs ^e)

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.
Posted
Updated 18-Mar-11 14:05pm
v2

1 solution

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 through System.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:
C++
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)
};


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!

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900