.NET Forum / Languages / Managed C++ / March 2008
Cannot pass a __delegate pointer to C++ function?
|
|
Thread rating:  |
glutz7878 - 08 Jul 2005 22:27 GMT I have no trouble passing __delegate ptrs to native C functions in DLLs, however when attempting to pass the __delegate ptr to a native C++ function in a DLL I get the following runtime exception: An unhandled exception of type 'System.EntryPointNotFoundException'.
This is confusing b/c if the entry point was not found, I would think I'd get an unresolved symbol error during linking. Furthermore, I can successfully pass void, int *, and function pointers, etc to C++ DLL functions, but this error persists when attempting to pass a __delegate pointer, which is used for callbacks to managed C++ functions.
Here is the relevant code snippet - the DLL code simply contains stubs of the functions called here:
#include "stdafx.h" #using <mscorlib.dll>
using namespace System; using namespace System::Runtime::InteropServices;
__delegate void testCB(); [DllImport("unmdll.dll")] void fnunmdll_2(testCB *UpdateProgMeter);
int fnunmdll_0(void); void fnunmdll_1(int *x);//testCB *UpdateProgMeter);
__gc class C1 { public: static void handleCB() { return; } };
int _tmain() { int k = 9;
//always works (as both C/C++) fnunmdll_0();
//always works (as both C/C++) fnunmdll_1(&k);
testCB *pCB = new testCB(0, &C1::handleCB);
//if this is a C++ function expecting a function pointer, the aforementioned error occurs. If this is an extern "C" function, all is ok! fnunmdll_2(pCB);
return 0; }
As crazy as it sounds, I'm beginning to think this is not possible to do with native C++ functions.
Thanks in advance, George
Willy Denoyette [MVP] - 08 Jul 2005 23:18 GMT This has nothing to do with delegates, this is a C++ name mangling issue, your DllImport functions (fnunmdll_2) must use C linkage exports, or an appropriate .DEF file. extern "C" { ...
}
Willy.
>I have no trouble passing __delegate ptrs to native C functions in DLLs, > however when attempting to pass the __delegate ptr to a native C++ [quoted text clipped - 57 lines] > > Thanks in advance, George glutz7878 - 08 Jul 2005 23:35 GMT Thanks for the post but do you know why there are no problems when passing void or int *, even function pointers? Wouldn't they also have name mangling issues? It seems strange that the only thing that fails is passing __delegates.
Thanks again, George
glutz7878 - 09 Jul 2005 00:09 GMT Using a .DEF file to get rid of mangled names fixes the problem. extern C also works of course but the .Def is better.
If anyone can explain why this worked all along for all non-delegate types, i would really love to know. I'm not sure why name-mangling would affect the function call based on argument type.
Thanks, George
Willy Denoyette [MVP] - 09 Jul 2005 00:12 GMT > Thanks for the post but do you know why there are no problems when passing > void or int *, even function pointers? Wouldn't they also have name [quoted text clipped - 3 lines] > > Thanks again, George No, the diference is that you are calling the function through PInvoke ([DllImport("unmdll.dll")]), that means you are dynamically binding against the library and the entrypoint will be resolved at call time(that's why the linker doesn't complain), while in the other cases you are statically linking and the linker is able to resolve the functions called points.
Willy.
samm - 12 Mar 2008 01:58 GMT Thank you for your help. It works fine, but I have weird problem. It works only on one of my devices: HTC Touch phone. If I use HTC Mogul (the same Windows Mobile 6.0, but less memory) it does not. I have the same .net CF 2.0 on both.
thanks again.
Passing managed delegates to native functions as callbacks
> > Thanks for the post but do you know why there are no problems when passing > > void or int *, even function pointers? Wouldn't they also have name [quoted text clipped - 11 lines] > > Willy. Ben Voigt [C++ MVP] - 12 Mar 2008 16:35 GMT > Thank you for your help. It works fine, but I have weird problem. It > works only on one of my devices: HTC Touch phone. If I use HTC Mogul > (the same Windows Mobile 6.0, but less memory) it does not. I have > the same .net CF 2.0 on both. C++ interop doesn't work in the compact framework, but Marshal::GetFunctionPointerForDelegate does.
__delegate doesn't exist in .NET 2.0, that's .NET 1.x Managed Extensions for C++ syntax
Explain what you're trying to accomplish and what you're doing so far and we should be able to help you.
samm - 12 Mar 2008 18:11 GMT Sure.
1. I have C++ dll which needs to register callback in my C# application. This callback returns a string:
C# side:
public delegate void RegisterCallBackDelegateInt(System.IntPtr response); ... RegisterCallBackDelegateInt Callback; IntPtr callbackPointer; ...
Callback = new RegisterCallBackDelegateInt(RegisterCallBackInt); callbackPointer = Marshal.GetFunctionPointerForDelegate(Callback); GC.KeepAlive(callbackPointer); ret = RegisterCallBack(callbackPointer); ... public void RegisterCallBackInt(System.IntPtr response) { string myString = Marshal.PtrToStringUni(response); Log("Callback: " + myString); Marshal.FreeHGlobal(response); }
C++ side
extern "C" {
__declspec( dllexport ) HRESULT RegisterCallBack(void(*CB)(BYTE *xmlResult) );
};
It works fine on Touch HTC phone, but not on Mogul.
2. The reason I do that is because I do not have ability to wrap my C++ dll to C++ managed anymore. On win32 I can do that and my life is much better.
Thank you for your help.
Sam
> > Thank you for your help. It works fine, but I have weird problem. It > > works only on one of my devices: HTC Touch phone. If I use HTC Mogul [quoted text clipped - 9 lines] > Explain what you're trying to accomplish and what you're doing so far and we > should be able to help you. Ben Voigt [C++ MVP] - 12 Mar 2008 19:23 GMT > Sure. > [quoted text clipped - 40 lines] > > Thank you for your help. You are misusing GC.KeepAlive, so you will experience random failures whenever a collection takes place before the callback is finished. Use GCHandle.Alloc instead, on the delegate, not the native function pointer.
> Sam samm - 12 Mar 2008 20:25 GMT Thank you. Can you give me an example?
> > Sure. > > [quoted text clipped - 46 lines] > > > Sam Ben Voigt [C++ MVP] - 12 Mar 2008 21:32 GMT > Thank you. > Can you give me an example? First, the runtime should do this for you if you do the DllImport right (see the documentation for GCHandle.Alloc). But you can do it by hand.
Modifying your example:
RegisterCallBackDelegateInt Callback; IntPtr callbackPointer; Callback = new RegisterCallBackDelegateInt(RegisterCallBackInt); callbackPointer = Marshal.GetFunctionPointerForDelegate(Callback); ret = RegisterCallBack(callbackPointer);
GCHandle cbKeepAlive = GCHandle.Alloc(Callback); ...
// when the callback will no longer be used from native code cbKeepAlive.Free();
>>> Sure. >>> [quoted text clipped - 47 lines] >> >>> Sam samm - 13 Mar 2008 02:35 GMT I added code you recommended. My application works fine, but if I start another application and switch back to mine I get a crash.
If I stay in my app it works without any problems.
> > Thank you. > > Can you give me an example? [quoted text clipped - 67 lines] > >> > >>> Sam Ben Voigt [C++ MVP] - 13 Mar 2008 14:43 GMT > I added code you recommended. My application works fine, but if I > start another application and switch back to mine I get a crash. Switching applications usually triggers a GC.
Try changing GCHandle.Alloc(x) to GCHandle.Alloc(x, GCHandleType.Pinned)
> If I stay in my app it works without any problems. > [quoted text clipped - 70 lines] >>>> >>>>> Sam samm - 13 Mar 2008 18:48 GMT Does not work. If I switch without using callback no problems. I am suprised Microsoft released the product without straight forward feature of calling C++ dlls from .net. Managed C++ was working just fine for me as a glue between .net and C++ unmanaged.
> > I added code you recommended. My application works fine, but if I > > start another application and switch back to mine I get a crash. [quoted text clipped - 77 lines] > >>>> > >>>>> Sam Ben Voigt [C++ MVP] - 13 Mar 2008 21:26 GMT > Does not work. If I switch without using callback no problems. > I am suprised Microsoft released the product without straight forward > feature of calling C++ dlls from .net. Managed C++ was working just > fine for me as a glue between .net and C++ unmanaged. C++ interop is great (at least starting with 2005), but you're on Compact Framework so you can't use it.
Try taking out the GCHandle.Free entirely?
>>> I added code you recommended. My application works fine, but if I >>> start another application and switch back to mine I get a crash. [quoted text clipped - 78 lines] >>>>>> >>>>>>> Sam samm - 13 Mar 2008 22:01 GMT I do not call free at all. I got interop file and llok what happens: [pinvokeimpl][preservesig] int Averquest.Averquest::SendRequest(System.Byte[] ); int (I4_VAL) SendRequest(unsigned char *(ARRAY_BLIT_LPARRAY) );
[preservesig][delegate] void RegisterCallBackDelegateInt::Invoke(RegisterCallBackDelegateInt , IntPtr ); void (*)(INT_PTR (I_VAL) ) [preservesig][delegate] void RegisterCallBackDelegateInt::Invoke(RegisterCallBackDelegateInt , IntPtr ); void (*)(INT_PTR (I_VAL) ) [preservesig][delegate] void RegisterCallBackDelegateInt::Invoke(RegisterCallBackDelegateInt , IntPtr ); void (*)(INT_PTR (I_VAL) ) [preservesig][delegate] void RegisterCallBackDelegateInt::Invoke(RegisterCallBackDelegateInt , IntPtr ); void (*)(INT_PTR (I_VAL) ) [pinvokeimpl][preservesig] IntPtr SafeNativeMethods::LocalAlloc(int , int ); INT_PTR (I_VAL) LocalAlloc(int (I4_VAL) , int (I4_VAL) );
[pinvokeimpl][preservesig] IntPtr SafeNativeMethods::LocalAlloc(int , int ); INT_PTR (I_VAL) LocalAlloc(int (I4_VAL) , int (I4_VAL) );
[pinvokeimpl][preservesig] int Microsoft.WindowsMobile.Telephony.Phone::PhoneMakeCall(IntPtr ); int (I4_VAL) PhoneMakeCall(INT_PTR (I_VAL) );
[pinvokeimpl][preservesig] IntPtr SafeNativeMethods::LocalFree(IntPtr ); INT_PTR (I_VAL) LocalFree(INT_PTR (I_VAL) );
[pinvokeimpl][preservesig] IntPtr SafeNativeMethods::LocalFree(IntPtr ); INT_PTR (I_VAL) LocalFree(INT_PTR (I_VAL) );
> > Does not work. If I switch without using callback no problems. > > I am suprised Microsoft released the product without straight forward [quoted text clipped - 88 lines] > >>>>>> > >>>>>>> Sam
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|