Groups | Blog | Home
all groups > dotnet interop > april 2006 >

dotnet interop : Callback not being called


Bruce Parker
4/26/2006 10:15:02 AM
Below is some sample unmananged C++ code and managed C# code. The callback
does not fire when invoked from the timer in the unmanged code.

Any ideas?

Managed code:

[DllImport("NativeTest.dll")]
private static extern void
InitCallBackReturningStringFromTimer(CallBackDelegateReturningStringFromTimer
theCallBack,IntPtr[] ppStringArray,int nCount);

delegate void CallBackDelegateReturningStringFromTimer(IntPtr[]
theStrings,int nCount);

public void CallBackMethodStringFromTimer(IntPtr[] ppStringArray,
int nCount)
{
IntPtr myIntPtr;
String myString;

myIntPtr=Marshal.ReadIntPtr(ppStringArray[0]);
myString=Marshal.PtrToStringUni(myIntPtr);
myIntPtr = Marshal.ReadIntPtr(ppStringArray[1]);
myString = Marshal.PtrToStringUni(myIntPtr);
MessageBox.Show("In Callback from timer");
}

private void CallBackStringFromTimerButton_Click(object sender,
EventArgs e)
{

CallBackDelegateReturningStringFromTimer theCallBack = new
CallBackDelegateReturningStringFromTimer(CallBackMethodStringFromTimer);

InitCallBackReturningStringFromTimer(theCallBack, null, 0);
}

C++ unmanaged code

typedef void (*callBackTypeReturningStrings)(LPTSTR* ppStringArray, int
cArray);

callBackTypeReturningStrings gTheCallBackReturningStrings;
unsigned int timerHandle;

NATIVETEST_API void
InitCallBackReturningStringFromTimer(callBackTypeReturningStrings
theCallBack,LPTSTR* ppStringArray, int cArray)
{
gTheCallBackReturningStrings = theCallBack;
timerHandle = SetTimer(NULL,NULL,5000,TimerProc);
}

void CALLBACK TimerProc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime )
{
LPTSTR ppStringArray[2];

ppStringArray[0]=SysAllocString(L"string 1");
ppStringArray[1]=SysAllocString(L"string 2");

gTheCallBackReturningStrings(ppStringArray,2);
SysFreeString(ppStringArray[0]);
SysFreeString(ppStringArray[1]);
KillTimer(NULL,timerHandle);
}
v-phuang NO[at]SPAM online.microsoft.com (
4/27/2006 6:29:09 AM
Hi

First of all, I would like to confirm my understanding of your issue.
From your description, I understand that you want to set a callback in .NET
code, so that when the unmanaged C++ function tried to call the function
pointer(callback), it will call the .NET managed code.

Have I fully understood you? If there is anything I misunderstood, please
feel free to let me know.

Based on my research, I think you may try to take a look at the link below
which will demostrate how to use call back between managed and unmanaged
code.
Global System Hooks in .NET
http://www.codeproject.com/csharp/GlobalSystemHook.asp

Here are some code snippet for your reference.
[DllImport("user32")]
public static extern int EnumWindows(CallBack x, ref IntPtr y);
public delegate bool CallBack(IntPtr hwnd, ref IntPtr lParam);
private void button1_Click(object sender, System.EventArgs e)
{
CallBack myCallBack = new CallBack(Report);
IntPtr lp = this.Handle;
EnumWindows(myCallBack, ref lp);
Debug.WriteLine("button1_Click: "+lp.ToInt32().ToString("X"));
}

public static bool Report(IntPtr hwnd,ref IntPtr lParam)
{
string str = "Window handle is :" +hwnd.ToInt32().ToString("X");
Debug.WriteLine(str);
if (hwnd == lParam)
{
Debug.WriteLine("Matched!"+"hwnd:"
+hwnd.ToInt32().ToString("X")+"lParam:"+lParam.ToInt32().ToString("X"));
lParam = new IntPtr(0x1234);//return
return false;
}
return true;


}

Please Apply My Suggestion Above And Let Me Know If It Helps Resolve Your
Problem.

If you still have any concern, please feel free to post here.


Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Bruce Parker
4/27/2006 6:59:01 AM
Hi Peter,

Thanks for the reply.

Please take a look at my sample code. This code will work if I do not
specify that I want an array of strings back from the unmanaged code.

I need to be able to return an array of strings back from the unmanaged code.

[quoted text, click to view]
v-phuang NO[at]SPAM online.microsoft.com (
4/28/2006 12:00:00 AM
Hi,

Based on my research, you need to change two place.
1. change the CallingConvention of the C++ export function.

typedef void (__stdcall *callBackTypeReturningStrings)(LPTSTR*
ppStringArray, int cArray);

callBackTypeReturningStrings gTheCallBackReturningStrings;
unsigned int timerHandle;

void CALLBACK TimerProc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime )
{
LPTSTR ppStringArray[2];

ppStringArray[0]=SysAllocString(L"string 1");
ppStringArray[1]=SysAllocString(L"string 2");

gTheCallBackReturningStrings(ppStringArray,2);
SysFreeString(ppStringArray[0]);
SysFreeString(ppStringArray[1]);
KillTimer(NULL,timerHandle);
}

extern "C" CPPDLLFUNCTIONPOINTER_API void
InitCallBackReturningStringFromTimer(callBackTypeReturningStrings
theCallBack,LPTSTR* ppStringArray, int cArray)
{
gTheCallBackReturningStrings = theCallBack;
timerHandle = SetTimer(NULL,NULL,5000,TimerProc);
}

2. Change the .NET call back function signature, we need to tell the .NET
runtime, how many items we need to marshalling. And we need to use
PtrToStringBSTR, because the SysAllocString will return a BSTR.

[DllImport(DLLPATH, CallingConvention = CallingConvention.StdCall)]
private static extern void
InitCallBackReturningStringFromTimer(CallBackDelegateReturningStringFromTime
r theCallBack, IntPtr[] ppStringArray, int nCount);
delegate void CallBackDelegateReturningStringFromTimer([In,Out,
MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] IntPtr[] theStrings, int
nCount);
public void CallBackMethodStringFromTimer([In,Out,
MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] IntPtr[]
ppStringArray, int nCount)
{
String myString;
myString = Marshal.PtrToStringBSTR(ppStringArray[0]);
Console.WriteLine(myString);
myString = Marshal.PtrToStringBSTR(ppStringArray[1]);
Console.WriteLine(myString);
Console.WriteLine("In Callback from timer");
}

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Bruce Parker
4/28/2006 5:29:01 PM
Hi Peter,

Thanks for the help you are providing me.

Were you able to get this code to work in an application? My unmanaged C++
code is targeted as a Smart Device DLL. My application is a smart device
application. I took the modifications you suggested and placed into mine.
The callback in the unmanaged code appears to fire, but the managed code
never receives it. I appreciate any help you can provide.



[quoted text, click to view]
v-phuang NO[at]SPAM online.microsoft.com (
5/1/2006 12:00:00 AM
Hi

This newsgroup is for Desktop Interop only, for embedded development,
please post in the newsgroup below.
microsoft.public.pocketpc.developer
or
microsoft.public.dotnet.framework.compactframework

Thanks for your understanding!

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
AddThis Social Bookmark Button