原作者:Saurabh Dasgupta<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
文章出處:http://www.codeguru.com/activex/COMStepByStep.html
譯者的話,首先要聲明的,這以一篇來自於WWW.CODEGURU.COM上的文章,我只是將其翻譯。要告訴您的是,如果您已經是一個COM高手了,請您不要浪費時間來讀它了,如果您想給我這個新手一點意見,我不勝感激。如果您是學習COM的入門者,我覺得,他還是很有幫助的,至少,你可以通過手動的添加代碼而不是使用Visual C++的嚮導來完成,讓你瞭解要實現一個簡單的com對象,所需要完成的工作。因爲本人曾寫了一點很淺的文字,因爲沒有寫下內容介紹,遭到了非議。所以在此寫下這些文字,希望讓別人很快的瞭解文章的內容,讀於不讀,有所選擇。願和所有初學者共勉。
目錄:
介紹
接口
第一步:創建IDL文件
第二步:生成類型庫
第三步:從IAdd繼承
第四步:實現IAdd的方法
第五步:實現IUnkown
第六步:類工廠
第七步:實現IClassFactory的方法
第八步:實現DllGetClassObject
第九步:實現DllCanUnloadNow
第十步:DllRegisterServer和UnregisterServer
第十一步:將IDL文件插入到工作空間中
第十二步:在Visual Basic 中使用COM剛創建的對象
第十三步:分析我們剛創建的所有文件
第十四步:在ActiveX DLL中嵌入類型庫
第十五步:從Visual C++客戶方使用剛創建的COM對象
介紹
對於我來說,理解COM(Component Object Model)至少是不止一次的冒險旅行了。我相信,每一個希望理解COM背後基本理論的程序員,一定有過使用沒有MFC/ATL的模板和宏幫助下的C++語言寫了至少一個以上的簡單的COM對象。在這篇文章中,我會根據COM的基本原理,介紹創建一個簡單COM對象的步驟。這個創建的組件可以在VC/VB的客戶端使用。
作爲練習,我們會試圖設計一個COM對象,實現一個假想的超級快速的加法算法。這個組件有兩個長整型(long type)的參數,其返回值也是一個長整型數,是我們加法算法的結果。下面我們就開始設計這個接口。
接口
COM對象的接口,我們不會談到實際的實現,而是要談論使用這個COM對象並與之通信的方法簽名(method signatures)。我們將會命名我們的接口爲IAdd。 這個接口的聲明使用接口定義語言來完成(Interface Definition Language --IDL),接口定義語言是用來定義函數簽名(Function Signatures)的,它使用一種獨立於編程語言的格式,這有助於RPC組織從一個計算機到另一個的打包、分發和解包的參數。在我們的接口IAdd中,我們有兩個方法SetFirstNumber和SetSecondNumber,這兩個方法用來傳遞加法使用的參數。然後,還有另外一個方法DoTheAddition,他用來計算實際的結果並將結果返回給客戶。
第一步:創建IDL文件
創建一個新的win32 DLL工程(命名爲AddObj)。接下來的所有文件將被創建到此文件夾。創建一個空文件並鍵入下面的內容,把它保存爲IAdd.idl。接口標識符使用uuidgen.exe生成(uuidgen.exe是一個dos文件,可以在命令行直接運行它)
import "unknwn.idl";
[
object,
uuid(1221db62-f3d8-11d4-825d-00104b<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />3646c0),
helpstring("interface IAdd is used for implementing a super-fast addition Algorithm")
]
interface IAdd : IUnknown
{
HRESULT SetFirstNumber(long nX1);
HRESULT SetSecondNumber(long nX2);
HRESULT DoTheAddition([out,retval] long *pBuffer);
};
[
uuid(3ff1aab8-f3d8-11d4-825d-00104b3646c0),
helpstring("Interfaces for Code Guru algorithm implementations .")
]
library CodeGuruMathLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
interface IAdd;
}
第二步 生成類型庫
使用IDL編譯器MIDL.EXE編譯接口定義文件IAdd.idl。編譯完成後,將會生成以下的文件:
IAdd.h |
包含C++格式的接口聲明 |
dlldata.c |
包含代理DLL的代碼。當在一個不同的處理器/計算機上調用對象時使用 |
IAdd.tlb |
二進制文件。使用一個定義好的格式完全的描述我們的IAdd接口和它所有的方法。這個文件和COM組件分發給所有的客戶。 |
IAdd_p.c |
包含代理DLL的列集代碼。當在一個不同的處理器/計算機上調用對象時使用 |
IAdd_i.c |
包含接口ID(IID) |
(譯者注:編譯方法爲,如過你的機器已經安裝了Visual Studio環境的話,那麼你可以直接從命令行寫入如下的語句,midl.exe ../ AddObj/iadd.idl )
第三步 從IAdd繼承
我們將在此步驟中創建一個COM對象。創建一個新文件(AddObj.h),聲明一個C++類,命名這個類爲CAddObj,從接口IAdd繼承(在文件IAdd.h)。記住,IAdd繼承自IUnknown,IUnknown是一個抽象基類。因而我們不得不像IUnknown一樣爲抽象基類IAdd聲明所有的方法。
///////////////////////////////////////////////////////////
//
//AddObj.h
//Contains the C++ class declarations for implementing the IAdd
//interfaces
//
#include "IAdd.h"
extern long g_nComObjsInUse;
class CAddObj :
public IAdd
{
public:
//IUnknown interface
HRESULT __stdcall QueryInterface(
REFIID riid ,
void **ppObj);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//IAdd interface
HRESULT __stdcall SetFirstNumber( long nX1);
HRESULT __stdcall SetSecondNumber( long nX2);
HRESULT __stdcall DoTheAddition( long *pBuffer);
private:
long m_nX1 , m_nX2; //operands for addition
long m_nRefCount; //for managing the reference count
};
///////////////////////////////////////////////////////////
COM指南 (Step by Step COM Tutorial)-中 COM指南 (Step by Step COM Tutorial)-下(1) COM指南 (Step by Step COM Tutorial)-下(2)