Objective Toolkit : Chapter 30 Introduction to Objective Toolkit for ATL : Marshaling Classes
Marshaling Classes
From time to time, COM developers need to move an interface pointer from one apartment to another (for example, if two threads need access to the same object). The process of getting an interface pointer from one apartment to another is called marshaling the interface pointer.
OTL provides marshaling help in several forms. First, OT/ATL contains a class named OtlGIT to help you work with the Global Interface Table. The OtlGIT class manages the IGlobalInterfaceTable interface for you so you no longer need to call CoCreateInstance() to retrieve the interface.
Here’s an example illustrating how to use the global interface helper.
 
#include <OtlGIT.h>
 
using namespace StingrayOTL;
 
OtlGIT* potlgit;
 
DWORD g_dwMarshalThis = 0;
 
DWORD WINAPI ThreadProc(void *pv)
{
IMarshalThis* pMarshalThis = NULL;
HRESULT hr = CoInitializeEx(0,
COINIT_APARTMENTTHREADED);
 
IMarshalThis* pRaw = (IMarshalThis*)pv;
 
if(pRaw)
{
hr = pRaw->Method2(3);
if(FAILED(hr))
{
printf("Raw pointer didn't work \n");
} else
{
printf("Raw pointer did work \n");
pRaw->Release();
}
}
 
// Unmarshal the interface pointerfrom the GIT
hr = potlgit->GetInterface(g_dwMarshalThis,
IID_IMarshalThis,
(void**)&pMarshalThis);
 
if(SUCCEEDED(hr))
{
short s;
 
// Use the pointer
hr = pMarshalThis->Method1(34, &s);
if(SUCCEEDED(hr))
{
printf("Marshaled pointer did work \n");
} else
{
printf("Marshaled pointer didn't work \n");
}
 
// Release the interface pointers.
pMarshalThis->Release();
}
 
// Leave the apartment.
CoUninitialize();
return 0;
}
 
int main(int argc, char* argv[])
{
// Enter the multi-threaded apartment. We're all partying in
// the same room now.
CoInitializeEx(0, COINIT_MULTITHREADED);
 
IMarshalThis* pMarshalThis = NULL;
 
potlgit = new OtlGIT;
if(!potlgit)
return 0;
 
// CoCreateInstance on the SomeATLObj
HRESULT hr = CoCreateInstance(CLSID_MarshalThisObj,
NULL,
CLSCTX_INPROC_SERVER,
IID_IMarshalThis,
(void**)&pMarshalThis);
 
if(SUCCEEDED(hr)) {
// Register the interface pointer with the global
// interface table
potlgit->RegisterInterface(pMarshalThis,
IID_IMarshalThis,
&g_dwMarshalThis);
 
// go ahead and call these functions from this apartment.
// Then create a new thread in a new apartment
DWORD dwTID;
HANDLE hthread = CreateThread(0, 0,
ThreadProc,
pMarshalThis,
0, &dwTID);
 
// Wait for the thread to exit and close the handle.
// allow STA to dispatch calls
AtlWaitWithMessageLoop( hthread );
CloseHandle(hthread);
 
pMarshalThis->Release();
potlgit->RevokeInterface(g_dwMarshalThis);
 
} else
{
printf("Couldn't create CLSID_MarshalThisObj\n");
}
 
if(potlgit)
{
delete potlgit;
}
 
printf( "\nPress any key to exit..." );
getchar();
 
CoUninitialize();
return 0;
}