![]() |
|
|
|
#1 |
|
Guest
Posts: n/a
|
How to interop .Net client and COM DLL?
Using VS2005 SP1, I have a C++ COM DLL and a C# client.
If the C++ and MIDL source use type INT_PTR and the C# client uses type IntPtr, then the result works in x86 (32 bit) but doesn't compile in x64 (64-bit). The C# compiler gives error messages like Error CS1503: Parameter '6': cannot convert from 'out System.IntPtr' to 'out long'. MSDN suggests that the C++ and MIDL source should use type void* instead. http://msdn2.microsoft.com/en-us/library/sak564ww.aspx * COM value type COM reference type System type * void * void ** System.IntPtr This MSDN page does not mention native type INT_PTR at all, it says void*. I couldn't imagine what difference it would make, but I still can't find any other solution, so I obeyed this page. Now the MIDL compiler gives error messages like error MIDL2139: type of the parameter cannot derive from void or void * Does anyone know how to do COM interop in x64? Advertisement |
|
|
#2 |
|
Guest
Posts: n/a
|
Re: How to interop .Net client and COM DLL?
I guess this is part of the third-best answer:
http://msdn2.microsoft.com/en-us/lib...20(vs.71).aspx tlbimp, ildasm, notepad, ilasm. I changed a few parameter types from int64 to native int. Then the C# compiler saw them as IntPtr, matching the IntPtr variables in the C# client code. It still seems to me that the best answer would be for MIDL's INT_PTR to translate to IL's native int automatically, instead of translating to int32 or int64 depending on the compilation environment. Does anyone know why that doesn't happen? It still seems to me that the second-best answer would be for the C# compiler in an x64 environment to consider IntPtr and Int64 to be compatible, as the C# compiler in an x86 environment does consider IntPtr and Int32 to be compatible. Does anyone know why that doesn't happen? "Norman Diamond" <ndiamond@community.nospam> wrote in message news:u0q10f5DIHA.3980@TK2MSFTNGP03.phx.gbl... > Using VS2005 SP1, I have a C++ COM DLL and a C# client. > > If the C++ and MIDL source use type INT_PTR and the C# client uses type > IntPtr, then the result works in x86 (32 bit) but doesn't compile in x64 > (64-bit). The C# compiler gives error messages like > Error CS1503: Parameter '6': cannot convert from 'out System.IntPtr' > to 'out long'. > > MSDN suggests that the C++ and MIDL source should use type void* instead. > http://msdn2.microsoft.com/en-us/library/sak564ww.aspx > * COM value type COM reference type System type > * void * void ** System.IntPtr > > This MSDN page does not mention native type INT_PTR at all, it says void*. > I couldn't imagine what difference it would make, but I still can't find > any > other solution, so I obeyed this page. Now the MIDL compiler gives error > messages like > error MIDL2139: type of the parameter cannot derive from void or void * > > Does anyone know how to do COM interop in x64? > |
|
|
#3 |
|
Guest
Posts: n/a
|
Re: How to interop .Net client and COM DLL?
Norman,
>It still seems to me that the best answer would be for MIDL's INT_PTR to >translate to IL's native int automatically, instead of translating to int32 >or int64 depending on the compilation environment. Does anyone know why >that doesn't happen? INT_PTR is a typedef that maps to int or __int64 depending on platform (defined in BaseTsd.h). I believe the fact that it's pointer sized is lost already in the typelib compilation process (you can check by looking at the tlb file in OleView). >It still seems to me that the second-best answer would be for the C# >compiler in an x64 environment to consider IntPtr and Int64 to be >compatible, as the C# compiler in an x86 environment does consider IntPtr >and Int32 to be compatible. Does anyone know why that doesn't happen? Compatible in what way? In your original message it sounds like you got something like this to work static void Main() { IntPtr p; Foo(out p); } static void Foo(out int i) { i = 42; } But that gives a compile error for me. >> This MSDN page does not mention native type INT_PTR at all, it says void*. >> I couldn't imagine what difference it would make, but I still can't find >> any >> other solution, so I obeyed this page. Now the MIDL compiler gives error >> messages like >> error MIDL2139: type of the parameter cannot derive from void or void * >> >> Does anyone know how to do COM interop in x64? You get that error because a void* doesn't carry enough type information for marshaling code. But if that's not needed (for in-proc, same apartment calls) you can apply the [local] attribute to the method. Mattias -- Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup. |
|
|
#4 |
|
Guest
Posts: n/a
|
Re: How to interop .Net client and COM DLL?
Advertisement "Mattias Sjogren" <mattias.dont.want.spam@mvps.org> wrote in message
news:eiuBHkUEIHA.4400@TK2MSFTNGP04.phx.gbl... > Norman, > >>It still seems to me that the best answer would be for MIDL's INT_PTR to >>translate to IL's native int automatically, instead of translating to >>int32 or int64 depending on the compilation environment. Does anyone know >>why that doesn't happen? > > INT_PTR is a typedef that maps to int or __int64 depending on platform > (defined in BaseTsd.h). I believe the fact that it's pointer sized is lost > already in the typelib compilation process (you can check by looking at > the tlb file in OleView). I looked at the C# error message and didn't need to look at OleView ^_^ Yes I see that BaseTsd.h destroys the information. Do you know if it would be possible to put something in BaseTsd.h that converts to the .Net type System.IntPtr instead? Just for MIDL compilations of course. (C++ compilations will still need the underlying type.) >>It still seems to me that the second-best answer would be for the C# >>compiler in an x64 environment to consider IntPtr and Int64 to be >>compatible, as the C# compiler in an x86 environment does consider IntPtr >>and Int32 to be compatible. Does anyone know why that doesn't happen? > > Compatible in what way? In your original message it sounds like you got > something like this to work > > static void Main() > { > IntPtr p; > Foo(out p); > } > > static void Foo(out int i) { i = 42; } > > But that gives a compile error for me. You are right, it yields a compile error. The Foo in my case was a C++ COM method, but that doesn't matter at the moment. In my older code, there were two crucial differences which I forgot. The method used to return only one value, so it was the return type instead of being an out parameter. And indeed even for that there was no built-in compatibility, but a cast solved it trivially. So this interop problem is identical for both x86 and x64. out IntPtr seems to be impossible (except by hand editing with tlbimp -> ildasm -> notepad -> ilasm). >>> This MSDN page does not mention native type INT_PTR at all, it says >>> void*. I couldn't imagine what difference it would make, but I still >>> can't find any other solution, so I obeyed this page. Now the MIDL >>> compiler gives error messages like >>> error MIDL2139: type of the parameter cannot derive from void or void >>> * >>> >>> Does anyone know how to do COM interop in x64? > > You get that error because a void* doesn't carry enough type information > for marshaling code. It does for what I want. My COM method returns two IntPtr values to the C# client (used to be just one as mentioned above). The IntPtr values need to be marshalled as either 32 or 64 bits. native int is working, it's just a pain that this manual process was required. > But if that's not needed (for in-proc, same apartment calls) you can apply > the [local] attribute to the method. Aha, I'll try that. Thank you. Of course it would be meaningless to send a pointer value out to a different process. A different thread shouldn't matter though. Advertisement |
| Thread Tools | |
| Display Modes | |
|
|
< Home - Windows Help - MS Office Help - Hardware Support >
| New To Site? | Need Help? |