Can't invoke a COM visible method with IntPtr parameter.  
Author Message
João da Nóbrega





PostPosted: Common Language Runtime, Can't invoke a COM visible method with IntPtr parameter. Top

Hello:

Apparently it is impossible to invoke a .net method
that has a IntPtr parameter via a exported IDispatch interface. IDispatch.Invoke simply cannot find the method. I think this has to do with the default marshling of data types. IntPtr is marshaled into a VT_INT where VT_INT is marshaled back into a .net Int32. To my knowledge there is no variant type that gets marshaled into an IntPtr. We can confirm this in the Default Marshaling for Objects microsoft article.
If this is true, trying to export such an interface to COM should result in an error or at least in a warning, yet there is non, and the TLB is successfully created making you assume that method is actually invokable.

Regards,
JGN.


.NET Development23  
 
 
Jonas Nordlund (MECAD)





PostPosted: Common Language Runtime, Can't invoke a COM visible method with IntPtr parameter. Top

Hmm, I think I am in this situation too now. Smile

I'm trying to send a HWND over COM but get an "E_NOTIMPLEMENTED" error if trying to call a COM visible C# method using IntPtr as an argument from C++ with a HWND. This error goes away if I use a simple "int" type in the C# class, but that's of course a big no-no if this is to be portable to Win64 later on. And in either case, IntPtr looks pretty bad here, because the generated .tlb from that makes it take "COM long"'s, which I think are all 32-bit values. Or will this solve itself if I'd re-compile this on a 64-bit OS Will it then automagically generate a 64-bit value for the .tlb Or am I too look at this differently and use e.g. an object in C#, generating a VARIANT type in the .tlb And perhaps use some MarshalAs attribute

Anyway, I then though -- what if I try to take this as a 64-bit value Who cares if I waste half of that on 32-bit systems So I declared it as a "long" (i.e. System.Int64) in C# and the generated .tlb file now indeed takes something of type "int64". Over in C++ land that calls this, I then thought I'd wrap this value in a CComVariant before calling the method, and everything looked fine since that class takes a LONGLONG in its constructor, which maps to a native __int64 type on 64-bit editions of Windows, or a double on 32-bit editions (since doubles internally use 8 bytes / 64 bits). However, and here's the catch, Windows XP and higher seems required for the LONGLONG declaration, and since we have a few Windows 2000 clients, that won't be the perfect solution either. ;-) Maybe one can send a pointer as a double and take a double in C#, then casting it to something else, but that really looks like a cludge, and I wonder if there's a "cleaner" way of doing this sort of pointer sending over COM