Click here to Skip to main content
Click here to Skip to main content

Global Interface Table: An Easy Way to Marshal an Interface Pointer

By , 1 Mar 2007
 

Introduction

Component Object Modeling (COM) and ActiveX Template Library (ATL) are the toughest areas in Windows programming, but as a Windows programmer, you daily encounter these and seldom face difficulty accessing a COM pointer created in one thread from another thread in a multithreaded environment. COM/ATL has the concept of marshalling and the usage of Global Interface table to cope up with this problem.

Here, I am demonstrating how to marshal an interface pointer from one thread to another worker thread with some quick code. ATL provides an interfaces called IGlobalInterfaceTable and a COM template class called CComGITPtr to help the programmer understand this concept easily..

In my example, I have a COM component with an interface IIGitTest, which I am going to marshal in the GitClient application. If you don't know how to create the COM component, please refer to my Step-by-Step Guide for Creating a COM component.

How to marshal the interface pointer from one apartment to another?

  1. First of all, we have to create a component exposing the IIGitTest with get/set property name and then create a MFC dialog based client application GitClient, which will access this interface from one apartment to another?
  2. Our component name is GitInterface. I will import the DLL using a #import directive since I don't want the namespace in the imported tlh and tli files, so I will use the no_namespace suffix with #import. I.e., in our example:
  3.  #import "..\\output\\GitInterface.dll" no_namespace 
  4. Now we can access our IIGitTest. We now add the member variable in our class like:
  5. IIGitTestPtr m_pToInterface;
  6. Allocate memory to our interface and don't forget to initialize the COM model in the application.
  7. CoInitialize(NULL);
    // initialize the com CLSID pclsid;
    CLSIDFromString(L"GitInterface.IGitTest.1",&pclsid);
    m_pToInterface.CreateInstance(pclsid);
  8. Now, give some values to our interface pointer. This will help us check if we are able to marshal our interface properly.
  9. TCHAR szValues[256]; 
    m_edtGitValue.GetWindowText(szValues,256); 
    CComBSTR bstrValues(szValues); 
    m_pToInterface->put_Value(bstrValues);
  10. Now unleash our GIT Code in the client application.
  11. CComGITPtr<IIGITTEST> pToGITTest(m_pToInterface);
    DWORD dwGitCookie = pToGITTest.Detach();

    You must be wondering what this dwGitCookie will do and how the template class is working? CComGITPtr is a template wrapper class, which encapsulates the IGlobalInterfaceTable interface. We are passing our interface pointer to the template class CComGITPtr, and in return it is returning the DWORD cookie, which will help us find our interface in the global interface table.

  12. Now create a thread which will get the IIGitTest pointer from the Global Interface table.
  13. /// Create thread to try marshalling 
    CreateThread(NULL,NULL,ThreadProc, 
       reinterpret_cast<LPVOID>(dwGitCookie),NULL,NULL);
  14. Now, initialize COM inside the new thread, and retrieve the cookie identification which we have sent through the lpParam parameter.
  15. CoInitialize(NULL);
    DWORD dwCookie = reinterpret_cast<DWORD>(lpParam);
  16. Now create the CComGITPtr object and pass dwCookie as the parameter, which will instruct the CComGITPtr object to search GIT and retrieve the interface pointer of our interface.
  17. CComGITPtr<IIGITTEST>pToGITTest(dwCookie);
  18. Now, just copy the interface pointer to our interface pointer using the CComGITPtr::CopyTO function.
  19. IIGitTest *pToGitPtr;
    pToGITTest.CopyTo(&pToGitPtr);
  20. Now, retrieve the value. Remeber step 5.
  21. CComBSTR bstValue; 
    pToGitPtr->get_Value(&bstValue); 
    MessageBoxW(NULL,bstValue,L"From Git Interface",MB_OK);

    The End :)

In this way, you can marshal an interface pointer from one thread to an other without thinking about the technicality of marshalling and other related stuff. Let us revise the process again.

Quick Revision

  1. Create an interface pointer and attach it to the GIT template class
  2. Retrieve the cookie from the GIT object
  3. In another thread, using a DWORD cookie, find the interface in the GIT table
  4. Copy the object into an interface pointer
  5. Voila, now you can use your interface without any exception :)

Reference

  1. When to use the Global Interface Table
  2. CComGITPtr Class

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

ThatsAlok
Software Developer
India India
Member
He used to have biography here Smile | :) , but now he will hire someone (for free offcourse Big Grin | :-D ), Who writes his biography on his behalf Smile | :)
 
He is Great Fan of Mr. Johan Rosengren (his idol),Lim Bio Liong (Great Programmer) , Nishant S(Is he need any introduction?) and DavidCrow and Believes that, he will EXCEL in his life by following there steps!!!
 

In October 2005, He joined the League of Visual C++ MVP Smile | :)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMarshalling: Using native DLLs in .NETmembermeukjeboer3 Sep '08 - 2:06 
Please take a look at the following article:
http://blog.rednael.com/2008/08/29/MarshallingUsingNativeDLLsInNET.aspx[^]
 
It is an in-depth article about how to use a native DLL (or C++ DLL) in your managed .Net code. The article shows which types are interoperable, how to import a DLL, how to pass strings, how to pass structures and how to de-reference pointers.
GeneralRe: Marshalling: Using native DLLs in .NETmember ThatsAlok 3 Sep '08 - 4:28 
i don't understand the similarity between articles!
 

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
Never mind - my own stupidity is the source of every "problem" - Mixture

cheers,
Alok Gupta
VC Forum Q&A :- I/IV
Support CRY- Child Relief and You/xml>

GeneralCalling DetachmemberJon Clayton30 Jul '08 - 6:31 
Once using the CComGITPtr you have to call CComGITPtr.Detach method.
If you want to use it more than once.
 
If you don't if you call it again KaBoom.
 

/////////////////////////////////////////////////////
CComGITPtr pToGIT(m_dwIntCookie);
IOPCServer* pOPCServer = NULL;
pToGIT.CopyTo(&pOPCServer);
 
// Use the interface pointer
pOPCServer->GetWhatever();
 
pToGIT.Detach(); // release the interface from the CComGITPtr
 
///////////////////////////////////////////////////////
 
Thanks for the article!

GeneralRe: Calling DetachmemberCellulose13 Aug '08 - 15:03 
John--Thanks so much for the note. Saved me a ton of grief and solved one of my problems!
GeneralRe: Calling Detachmemberachainard19 Aug '12 - 20:23 
Warning : Detach don't release interface it detach the interface, to release interface, you need to revoke it from GIT using pToGIT.Revoke ();
 
take a look on MSDN : http://msdn.microsoft.com/en-us/library/t62af25w.aspx
...

GeneralNice Work, but slightly careless...memberPandele Florin3 Apr '07 - 5:33 
1)At point 6,
CComGITPtr<IIGITTEST> pToGITTest(m_pToInterface);
should be:
CComGITPtr<IIGitTest> pToGITTest(m_pToInterface);
(it creates confusion)
 
2)You do not properly Revoke() the interface pointer from the Global Table anywhere.I don't think that the destructor of the interface pointer or the GIT does this properly(and in proper order)otherwise it would not have an Revoke()(I think).
 
3)The article further confuses any reader by the bad choice of name(s) for the demo COM object & interface:
"IIGitTest"
IT should not contain any reference to GIT, to be clear, which is which.
One more appropriate name would be :IITestComInterface or IISampleComInterface.
 
4) It does not specifically say that this does NOT work with VC 6.0 (ATL 3.0).
Some note in the almost invisible upper-right that says "it works on VS.NET2003, VS2005" AND NOT that "it works ONLY on VS.NET2003, VS2005" does not spare you from doing that.

It might seem minor to you, but for someone seeing this for the very first time and in a lot of hurry,those minor things might become BIG major problems.
 
In the rest it is basically a good article about an poorly documented ATL 7.0 feature(In MSDN).

GeneralRe: Nice Work, but slightly careless...member ThatsAlok 3 Mar '08 - 18:12 
Pandele Florin wrote:
In the rest it is basically a good article about an poorly documented ATL 7.0 feature(In MSDN).

 
thanks for nice and constructive feedback. will work on the thing you pointed out! thanks. and sorry for replying late!
 

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
Never mind - my own stupidity is the source of every "problem" - Mixture

cheers,
Alok Gupta
VC Forum Q&A :- I/IV
Support CRY- Child Relief and You/codeProject$$>

GeneralRe: Nice Work, but slightly careless...memberCellulose13 Aug '08 - 15:07 
Agree with everything here. I actually had some problems exactly as described--was in a hurry and didn't read real carefully. Caused me some frustration.
 
That all said, still a very helpful article. Thanks.
GeneralNice work :)memberVuNic14 Mar '07 - 19:55 
Good contributions dude! Beer | [beer] Cool | :cool:
 


Press: 1500 to 2,200 messages in just 6 days? How's that possible sir?
Dr.Brad :Well,I just replied to everything Graus did and then argued with Negus for a bit.

GeneralRe: Nice work :)memberThatsAlok14 Mar '07 - 20:12 
VuNic wrote:
Good contributions dude! Beer | [beer] Cool | :cool:

thanks Smile | :)

 

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow


cheers,
Alok Gupta
Global Interface Table: An Easy Way to Marshal an Interface Pointer[new]
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 1 Mar 2007
Article Copyright 2007 by ThatsAlok
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid