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); }
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.
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] ""Peter Huang" [MSFT]" wrote: > 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. >
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.
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] ""Peter Huang" [MSFT]" wrote: > 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. >
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.
Don't see what you're looking for? Try a search.
|