Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
I am having this scenario which needs your help.
I have a C# app that interops with a C DLL. My C# app has to pass two fuction pointers to the DLL for it callback. The DLL starts a timer and that fires a timer callback every second from which the C# callback be fired.
My code snippets
In C# I have this class.

namespace
{
public delegate void Callback1(int num);
public delegate void Callback2(bool isUpdated);
public class TView
{
        [DllImport("xx.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void StartUpdate(Callback1 func1, Callback2 func2);
	
	public void UpdateTview()
	{
        
		Callback1 a_CallBack = new Callback1(UpdateFunction1); 
		Callback2 b_CallBack = new Callback2(UpdateFunction2);  
		StartUpdate(a_Callback, b_Callback);  
	}
	public void UpdateFunction1(int n)
	{
	}
 	public void UpdateFunction2(bool isUpdated)
	{
	}
}
In my DLL I have the StartUpdate function as follows

__declspec(dllexport) void __cdecl StartUpdate( void (*Callback1)(int), void (*Callback2)(bool)
{
	/*start the timer here*/
	bool success = ::CreateTimerQueueTimer(
		&m_timerHandle,
		NULL,
		(WAITORTIMERCALLBACK)TimerFire,
		NULL,
		0,
		1000,
		WT_EXECUTEINTIMERTHREAD);
	
}
void TimerFire()
{
	printf("Timer Callback called");
	if(condition1)
	//(*Callback1)(10); //should call UpdateFunction1
	if(condition2)
	//(*Callback2)(true); //should call UpdateFunction2
}
How should I achieve this. I can pass one function pointer as lpparam of TimerFire, but how do I pass other function pointer to TimerFire()? Is there any other approach?
Your help is greatly appreciated.
Thanks in advance.
Posted
Updated 17-Mar-11 15:14pm
v2

Niklas is right. You should change the type of your timer function.

C++
//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);
}
 
Share this answer
 
Comments
Espen Harlinn 18-Mar-11 5:51am    
Good effort, instructive piece of code, my 5
Olivier Levrey 18-Mar-11 5:55am    
Thank you Espen.
Balaji Ganesan1 18-Mar-11 13:30pm    
Thanks much to both Olivier and Niklas. That did it. Thanks!!!!
Use the Parameter argument in the call. If you want to send more than one pointer, you will have to wrap it up in a std::pair, std::tuple, or a custom struct/class, who's pointer you supply to the function.

Btw, your TimerFire function should look like:
VOID CALLBACK WaitOrTimerCallback(
  __in  PVOID lpParameter,
  __in  BOOLEAN TimerOrWaitFired
);


Your type-cast fools the compiler.
 
Share this answer
 
v2
Comments
Olivier Levrey 18-Mar-11 4:59am    
Voted 5.
Dalek Dave 18-Mar-11 5:22am    
Good Call.
Espen Harlinn 18-Mar-11 5:50am    
Nice one, my 5

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