How to marshal interfaces across apartments in Visual C++ (206076)
The information in this article applies to:
- Microsoft Visual C++ 2005 Express Edition
- Microsoft Visual C++ .NET (2003)
- Microsoft Visual C++ .NET (2002)
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
This article was previously published under Q206076 Note Microsoft Visual C++ 2005, Microsoft Visual C++ .NET 2003, and Microsoft Visual C++ .NET 2002 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. SUMMARY Marshal.exe is a sample that shows the different ways of
marshaling an interface across apartments.MORE INFORMATION
The following file is available for download from the Microsoft Download Center: Download the Marshal.exe package now.Marshal.exe
For more information about how to download Microsoft support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591 How to obtain Microsoft support files from online services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help prevent any unauthorized changes to the file.
A Single-Threaded
Apartment (STA) is a thread that was initialized with CoInitialize() or
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED). Also, any other threads in the
same process that use COM must also call CoInitialize() or CoInitializeEx() to
initialize COM for its thread. If you create a COM object in one STA
thread, you cannot pass an interface pointer to another STA thread and call out
on that pointer. Since calls to STA objects are supposed to be serialized, COM
enforces this by only allowing one thread to call into the STA object (the
thread where it was created). If the interface pointer you pass to the second
STA thread is a pointer to a proxy, you will get an error HRESULT of 0x8001010E
or RPC_E_WRONG_THREAD (the application called an interface that was marshalled
for a different thread). If the interface pointer is a direct pointer to the
object, COM will not enforce serialization, you will not get the above error,
and the interface method call will be made. However, this is still illegal
behavior on the part of the client. You can still call methods on
the STA object from a different STA thread as long as you do it through a
proxy. A proxy is a copy of the interface that you get via
marshaling/unmarshaling. When you make a call through the proxy, COM makes a
thread switch and the call ends up executing in the context of the thread where
the STA object was created. There are three ways to marshal/unmarshal
an interface to another STA thread:
- CoMarshalInterThreadInterfaceInStream() and CoGetInterfaceAndReleaseStream(): One drawback to using this method is the interface can only be
unmarshaled once. That is, if you need access to the same object from several
STA threads, this method won't work.
- CoMarshalInterface() and CoUnMarshalInterface(): This method is more flexible since you can marshal the interface
once and unmarshal the interface as many times as you like; for example,
specifying MSHLFLGS_TABLEWEAK or MSHLFLGS_TABLESTRONG when marshaling the
interface. But it also requires more code since you have to create the IStream,
set the seek pointer and clean up the marshal packet via
CoReleaseMarshalData(). When marshaling pointers to a proxy you must have
Windows NT 4.0 Service Pack 4 or later, Windows 98 or Windows 95 with DCOM 1.2
or later installed. Also when using the MSHLFLGS_TABLESTRONG flag you must have
Windows 2000 or later.
- Global Interface Table(GIT): The GIT is a COM object that allows you to store an interface in
one STA thread and get access to it's proxy in another STA thread. This is only
available with Windows NT 4.0 Service Pack 3 or later, Windows 98 or Windows 95
with DCOM 1.1 or later installed.
Marshal.exe contains TSTMARSH which is the main project. This
contains an ATL EXE server that implements ITest. ITest has one method called
ToUpper(), which converts a string to uppercase. A sub-project called Client is
also included. Client.cpp is where all the marshaling/unmarshaling methods are
shown. Each method creates an instance of the Test object, marshals an ITest
interface and creates a thread. In each thread, an ITest interface is
unmarshaled and the method ToUpper() is called to convert a string. You should
see the output in the debug window of: "THIS IS OUTPUT FROM THREAD #N".
REFERENCES
For more information, click the following article number to view the article in the Microsoft Knowledge Base:
172314
Explanation of RPC_E_WRONG_THREAD error
Modification Type: | Major | Last Reviewed: | 1/9/2006 |
---|
Keywords: | kbArchitecture kbfile kbhowto kbSample kbThread KB206076 kbAudDeveloper |
---|
|