Groups | Blog | Home
all groups > dotnet interop > april 2008 >

dotnet interop : Problem with COM interface using IntPtr...


theunissen@comcast.net
4/22/2008 9:51:53 AM
Hi,

This message is related to a problem I posted a few days ago:

http://groups.google.com/group/microsoft.public.dotnet.framework.interop/browse_thread/thread/4d243fe978432c06/37881b961489f153?hl=en&lnk=st&q=Visual+Basic+X64+COM+parameter#37881b961489f153

I had a problem where INT"_PTR" in a com interface didn't show up as
"IntPtr"
inside Visual Basic. This problem was resolved by using a "HANDLE" or
"void*" inside the interface definition in the IDL file. To use the
"HANDLE" definition you should use the "[local]" IDL keyword in front
of the interface or interface function.

The problem I have now is since I changed the interfaces and use the
"[local]" key word in combination with void* (or HANDLE) it seems I
can no longer use these interfaces from
inside a different thread in Visual Basic. Using the interface on the
mainthread is no problem. Is this normal behavior, that once you use
void*, the threading is no longer supported?

I get the following message:

Unable to cast COM object of type 'CommonCPP.CImageEightClass' to
interface type 'CommonCPP.IImageEight'. This operation failed because
the QueryInterface call on the COM component for the interface with
IID '{4F6BD020-CFF2-49D2-853E-1816840A574D}' failed due to the
following error: Bad variable type. (Exception from HRESULT:
0x80020008 (DISP_E_BADVARTYPE)).


Also, how would I be able to bypass the "Strict On" complaining
about "IntPtr.Toin64" when trying to distinguish between x86 and x64
when I cannot use void* in the interfaces?

for example:

If _WIN64 Then
foo_Interface(variable.ToInt32)
Else
' The compiler complains here with option "Strict On"
when compiling for x86
foo_Interface(variable.ToInt64)
End If

theunissen@comcast.net
4/22/2008 4:15:11 PM
I figured it all out. Please read:

In order to have an interface display "as IntPtr" inside Visual Basic
one should define the parameter as HANDLE or void* inside the IDL
file. We already seen this. In addition,
to avoid the IDL compiler warning one should use "Local".

Now there is a problem, when using void* inside COM. This is a
threading issue. By default Visual basic runs as an STAThread. When
accessing any com component that uses void* inside a second Visual
Basic thread, the Application will crash. There seem to be some
marshalling problem, complaining about interface casting and
parameter problems. The solution for this would be to make all COM
classes 'free' threaded or 'both' threaded. This will then work when
running the application inside an MTAThread.

In my case, the MTAThread attribute caused me problems as well, since
I was still using some old ActiveX controls that must run inside a
STAThread. So, that's were it stopped for me.

Hopefully for someone else this will work.


[quoted text, click to view]
Willy Denoyette [MVP]
4/23/2008 1:49:44 AM
By marking an interface or method as 'local', you are explicitly stating
that this as a non remote-able interface or method, that means that the
interface or method cannot cross thread/apartment boundaries. So, what you
need, is to make sure that your component lives in the same apartment as the
creator's apartment, if you component is an 'apartment 'type, it needs an
STA thread to be created from, if it's marked 'both', it means it can live
in an MTA or an STA depending on the creators apartment.
So, in your scenario (an "apartment" type of object), you need to make sure
that the thread of the creator is initialized to enter an STA (this is done
by calling Thread.SetApartmentState). An object created from this thread
lives in the same apartment/thread as the creator , no marshaling has to be
done, so you can call the method marked as [local].

Willy.


[quoted text, click to view]
I figured it all out. Please read:

In order to have an interface display "as IntPtr" inside Visual Basic
one should define the parameter as HANDLE or void* inside the IDL
file. We already seen this. In addition,
to avoid the IDL compiler warning one should use "Local".

Now there is a problem, when using void* inside COM. This is a
threading issue. By default Visual basic runs as an STAThread. When
accessing any com component that uses void* inside a second Visual
Basic thread, the Application will crash. There seem to be some
marshalling problem, complaining about interface casting and
parameter problems. The solution for this would be to make all COM
classes 'free' threaded or 'both' threaded. This will then work when
running the application inside an MTAThread.

In my case, the MTAThread attribute caused me problems as well, since
I was still using some old ActiveX controls that must run inside a
STAThread. So, that's were it stopped for me.

Hopefully for someone else this will work.


[quoted text, click to view]


AddThis Social Bookmark Button