Invalid Variant crash

Invalid Variant crash

I have a situation where I've wrapped a Native C++ DLL with C++/CLI for eventual use in C#.

There are a few callback functions that are causing some issues at run time. Particularly, I get the following exception:

An unhandled exception of type 'System.Runtime.InteropServices.InvalidOleVariantTypeException' occurred in ToadWrapTest.dll

Additional information: Specified OLE variant is invalid.

On this line of code (C++/CLI):

public delegate int ManagedCallbackFunction (Object^ inst, const Object^ data); public delegate int UnManagedCallbackFunction (void* inst, const void* data);  ManagedCallbackFunction^ m_callbackFn;  int intermidiaryCallback(void * pInstance, const void * pData)     {	     	void* temp = (void*)pData;     	System::IntPtr ip1 = IntPtr(pInstance);     	System::IntPtr ip2 = IntPtr(temp);     	Object^ oInst = Marshal::GetObjectForNativeVariant(ip1);     	Object^ oData = Marshal::GetObjectForNativeVariant(ip2);     	//invoke the callback to c#     	//return m_callbackFn::Invoke(oInst, oData);     	return 0;     }; 

The reason I've made this "intermediary callback" was an attempt to circumvent the Invalid variant exception being thrown when I tried to directly map the delegate from C# to the native C++ code. As an attempted work-around, I declare a delegate on the C# side and pass that funcptr to the C++/CLI wrapper. I then pass the intermediary funcptr to the native C++ and just daisy chain the calls together.

What I know is that it all works in native C++ world. The problem is mapping the void* to the managed world. The following code shows the native C++ version of the callback:

int (*CallbackFunction) (void *inst, const void *data); 

If anyone can help here, I'd really appreciate it.

Exception catching best practice (c#/.net)


Where do uncaught exceptions go with asynchronous I/O
Are pInstance and pData really VARIANT? If they are, I would expect your callback function to be more strongly typed:.
Multipule Operations in a finally block
int (*CallbackFunction)(VARIANT *inst, VARIANT *data); 
If that's the case, in your code you should be able to look at the actual VARIANT to hand check it.

Python: How to ignore an exception and proceed? [duplicate]
If you are not really getting VARIANTs (ie, you are really just getting void * pointers), you shouldn't try to turn them into C# objects since there is no inherent meaning to them.

Is “Dying is Awesome” preferred?
They should get passed through as IntPtr.

Response.Redirect - using exceptions for flow control?
If you know that they should have some other type of inherent meaning, you need to marshal them as appropriate types..
Why can't a null-reference exception name the object that has a null reference?

VB.NET Continuously Adding One to a Text Box


Big Thanks to plinth on this one! I am posting the final solution below to anyone else who has to deal with 3rd party fun like this one! Please feel free to critique, as I am not done optimizing the code.

This may still be to roundabout a solution.. First, the callback functions became:.
public delegate int ManagedCallbackFunction (IntPtr oInst, IntPtr oData); public delegate int UnManagedCallbackFunction (void* inst, const void* data); ManagedCallbackFunction^ m_callbackFn; 
Big props on this one.

It just plain won't work if you try to cast from void* directly to Object^.

Using the IntPtr and my intermediary callback: .
int intermidiaryCallback(void * pInstance, const void * pData) {        void* temp = (void*)pData;     return m_callbackFn->Invoke(IntPtr(pInstance), IntPtr(temp)); }; 
We finally get a working model on the C# side with some massaging of the objects:.
public static int hReceiveTestMessage(IntPtr pInstance, IntPtr pData) {    // provide object context for static member function    helloworld2 hw = (helloworld2)GCHandle.FromIntPtr(pInstance).Target;    if (hw == null || pData == null)    {       Console.WriteLine("hReceiveTestMessage received NULL data or instance pointer\n");       return 0;    }     // populate message with received data    IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataPacketWrap(pData)));    DataPacketWrap dpw = (DataPacketWrap)GCHandle.FromIntPtr(ip2).Target;    uint retval = hw.m_testData.load_dataSets(ref dpw);    // display message contents    hw.displayTestData();     return 1; } 
I mention "massaging" the objects because the delegate is not specific to this callback function and I don't know what object pData will be until run time(from the delegates POV).

Because of this issue, I have to do some extra work with the pData object.

I basically had to overload the constructor in my wrapper to accept an IntPtr.

Code is provided for full "clarity":.
DataPacketWrap (IntPtr dp) {  DataPacket* pdp = (DataPacket*)(dp.ToPointer()); m_NativeDataPacket = pdp; }; 

98 out of 100 based on 78 user ratings 878 reviews