PageRenderTime 25ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/Visual Studio 2008/CppCOMClient/ReadMe.txt

#
Plain Text | 164 lines | 116 code | 48 blank | 0 comment | 0 complexity | 93611829a53dd7d459e9d326cce18f86 MD5 | raw file
  1. ========================================================================
  2. CONSOLE APPLICATION : CppCOMClient Project Overview
  3. ========================================================================
  4. /////////////////////////////////////////////////////////////////////////////
  5. Use:
  6. There are three basic ways you can use Automation or consume a COM server in
  7. a native client: MFC, #import, and C/C++.
  8. 1. C/C++
  9. The code in RawAPI.h/cpp demontrates the use of C/C++ and the COM APIs to
  10. consume the COM object ATLDllCOMServer.SimpleObject. The raw automation
  11. is much more difficult, but it is sometimes necessary to avoid the overhead
  12. with MFC, or problems with #import. Basically, you work with such APIs as
  13. CoCreateInstance(), and COM interfaces such as IDispatch and IUnknown.
  14. 2. #import
  15. The code in ImportDirective.h/cpp demonstrates the use of #import to automate
  16. a COM server, more specifically, a COM server written in .NET: CSDllCOMServer.
  17. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx), a new
  18. directive that became available with Visual C++ 5.0, creates VC++ "smart
  19. pointers" from a specified type library. It is very powerful, but often not
  20. recommended because of reference-counting problems that typically occur when
  21. used with the Microsoft Office applications. Unlike the direct API approach
  22. in RawAPI.h/cpp, smart pointers enable us to benefit from the type info to
  23. early/late bind the object. #import takes care of adding the messy guids to
  24. the project and the COM APIs are encapsulated in custom classes that the
  25. #import directive generates.
  26. The differences between early binding and late binding via smart pointers:
  27. Smart pointers make creating an object that supports early binding easy, so
  28. does it make creating a late bound object. The only difference between early
  29. binding and late binding via smart pointer is the .tlh and .tli files
  30. generated by the #import directive. If the target object supports early
  31. binding, the .tlh and .tli files will make use of the custom interface (not
  32. IDispatch) to call the target property/method directly. If the target COM
  33. object only support late binding, the smart pointer takes care of converting
  34. your method calls into GetIDsOfNames()s and Invoke()s of the IDispatch
  35. interface.
  36. 3. MFC
  37. With MFC, Visual C++ ClassWizard can generate "wrapper classes" from the type
  38. libraries. These classes simplify the use of the COM servers. Please refer to
  39. the sample MFCCOMClient.
  40. /////////////////////////////////////////////////////////////////////////////
  41. Project Relation:
  42. CppCOMClient -> ATLDllCOMServer
  43. CppCOMClient is the client application of the COM server ATLDllCOMServer.
  44. CppCOMClient -> CSDllCOMServer
  45. CppCOMClient is the client application of the COM server CSDllCOMServer.
  46. /////////////////////////////////////////////////////////////////////////////
  47. Build:
  48. CppCOMClient depends on ATLDllCOMServer, CSDllCOMServer. To build and run
  49. CppCOMClient successfully, please make sure ATLDllCOMServer and CSDllCOMServer
  50. are built and registered rightly.
  51. /////////////////////////////////////////////////////////////////////////////
  52. Creation:
  53. A. Creating the ATLDllCOMServer.SimpleObject COM object using C++ and
  54. the COM APIs (RawAPI.h/cpp)
  55. Step1. Add the automation helper function, AutoWrap.
  56. Step2. Initialize COM by calling CoInitializeEx, or CoInitialize.
  57. Step3. Get CLSID of the COM server using the API CLSIDFromProgID.
  58. Step4. Start the server and get the IDispatch interface using the API
  59. CoCreateInstance.
  60. Step5. Consume the COM object with the help of AutoWrap.
  61. Step6. Release the COM object
  62. Step7. Uninitialize COM for this thread by calling CoUninitialize.
  63. B. Creating the CSDllCOMServer.CSExplicitInterfaceObject COM object using the
  64. #import directive and smart pointers (ImportDirecive.h/cpp)
  65. Step1. Import the type library of the target COM server using the #import
  66. directive. If the COM object is a .NET component, mscorlib.tlb is also
  67. required to be imported.
  68. Step2. Build the project. If the build is successful, the compiler generates
  69. the .tlh and .tli files that encapsulate the COM server based on the type
  70. library specified in the #import directive. It serves as a class wrapper we
  71. can now use to create the COM class and access its properties, methods, etc.
  72. Step3. Create a COM object using the smart pointer. The class name is the
  73. original interface name (i.e. ICSExplicitInterfaceObject) with a "Ptr" suffix.
  74. We can use either the constructor of the smart pointer class or its
  75. CreateInstance method to create the COM object.
  76. Step4. Call the COM object's properties, methods through the smart pointer
  77. like this:
  78. spSimpleObj->FloatProperty = 1.2f;
  79. To access the methods of the smart pointer class itself (e.g. QueryInterface),
  80. use the dot syntax spSimpleObj.QueryInterface().
  81. Step5. It is necessary to catch the COM errors if the type library was
  82. imported without raw_interfaces_only and when the raw interfaces
  83. (e.g. raw_HelloWorld) are not used. For example:
  84. #import "XXXX.tlb"
  85. try
  86. {
  87. _bstr_t result = spSimpleObj->HelloWorld();
  88. }
  89. catch (_com_error &err)
  90. {
  91. }
  92. The above code snippet is equivalent to:
  93. #import "XXXX.tlb"
  94. _bstr_t result;
  95. HRESULT hr = spSimpleObj->raw_HelloWorld(result.GetAddress());
  96. if (FAILED(hr)
  97. {
  98. }
  99. And it is also the same as:
  100. #import "XXXX.tlb" raw_interfaces_only
  101. _bstr_t result;
  102. HRESULT hr = spSimpleObj->HelloWorld(result.GetAddress());
  103. if (FAILED(hr)
  104. {
  105. }
  106. Step6. It is said that the smart pointers are released automatically, so we
  107. do not need to manually release the COM object.
  108. Step7. Uninitialize COM for this thread by calling CoUninitialize.
  109. /////////////////////////////////////////////////////////////////////////////
  110. References:
  111. COM Programming by Example: Using MFC, ActiveX, ATL, ADO, and COM+
  112. By John E. Swanke
  113. http://www.amazon.com/COM-Programming-Example-ActiveX-CD-ROM/dp/1929629036
  114. COM Interop Sample: COM Client and .NET Server
  115. http://msdn.microsoft.com/en-us/library/2w30w8zx.aspx
  116. /////////////////////////////////////////////////////////////////////////////