使用atl_com建立第一個本機伺服器
vc6
1.file-->new-->project--->atl com project
設定工程名:LocalServer
2.在server type 下選擇 executable ,之後選擇 finish
3.系統自動產生了一些檔案其中比較重要的有:
localserver.idl// 介面定義檔案
localserver.cpp// 可執行檔(編譯串連後產生 localserver.exe )
LocalServerps.mk// makefile
3.在 localserver.idl 加入新的介面定義
//如果不知道上面的東西的含義那麼去補補idl
//注意你可以使用想到來產生一個介面,而且想到還會產生和這個介面對應的組件(實現這個介面的類)
//使用方式如下:insert-->new atl object -->選擇object 中的simple object-->
之後會彈出一個對話方塊atl object wizard properties,選擇names,在Shortname裡填入Mathb別的框會自動產生。
之後選擇attribute,選擇appartment ,custom, yes ,support isuppoerterrorinfo
選擇ok,我們成功地在idl中加入了一個新的介面IMath,並且定義了一個新的組件CMath,這個組件實現了IMath,之後我們會讓這個組件實現更多的介面。。
這時系統新組建檔案math.h .cMath的標頭檔。
math.cpp CMath的實現檔案。
Math.rgs math組件的registar指令檔。有了他你就不用自己寫把組件註冊到註冊表的東西了
4.為IMath加入函數Add
在Classview中,游標放在IMath點又建選擇Add method .之後填入傳回值,函數名,參數
選擇確定,同時系統還在CMath加入了相應的代碼
//到這裡系統為idl檔案加入了如下內容:
[
object,
uuid(73DEDCFD-C87B-4E68-B6D1-A36FA3316DCD),
helpstring("IMath Interface"),
pointer_default(unique)
]
interface IMath : IUnknown
{
[helpstring("method Add")] HRESULT Add([in]int ipara1,[in]int ipara2,[out]int *pResult);
};
//為math.h加入了如下內容
// CMath
class ATL_NO_VTABLE CMath :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMath, &CLSID_Math>,
public ISupportErrorInfo,
public IMath,//...........
public IAdvancedMath//.....................
{
public:
CMath()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_MATH)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMath)
COM_INTERFACE_ENTRY(IMath)
COM_INTERFACE_ENTRY(IAdvancedMath)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// IMath
public:
STDMETHOD(Add)(/*[in]*/int ipara1,/*[in]*/int ipara2,/*[out]*/int *pResult);//。,。。。。
public:
//IAdvancedMath
//手動加入的介面
STDMETHOD(AdvancedAdd)(/*in*/int ipara1,/*[in]*/int ipara2,/*[out]*/int *pResult);
};
//對math.cpp加入的內容
STDMETHODIMP CMath::Add(int ipara1, int ipara2, int *pResult)
{
// TODO: Add your implementation code here
*pResult = ipara1 +ipara2;
cout<<"CMath::Add/n";
return S_OK;
}
5.手動加入新介面IAdvancedMath(上面使用的嚮導就是每次定義一個介面,同時為他弄一個組件。所以不能利用嚮導來為一個組件加入多個介面)。並加入一個函數
在localserver.idl中加入:
//add manual
[
object,
uuid(63FFA301-5BB0-4e0a-95CF-92C22FF1B796),
helpstring("IAdvancedMath Interface"),
pointer_default(unique)
]
interface IAdvancedMath : IUnknown
{
//加入的函數
[helpstring("method Add")] HRESULT AdvancedAdd([in]int ipara1,[in]int ipara2,[out]int *pResult);
};
[
uuid(0C01D7A4-D53A-4DF2-9D7A-1F76140E1C04),
version(1.0),
helpstring("LocalServer 1.0 Type Library")
]
library LOCALSERVERLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(82139624-D5FF-4418-8A11-EAA7EF381147),
helpstring("Math Class")
]
coclass Math
{
[default] interface IMath;//使用想到自動加入的
interface IAdvancedMath;//我們加入的
};
};
為CMath加入 public IAdvancedMath,使之繼承IAdvancedMath,//...........如上。
為CMath加入
public:
//IAdvancedMath
STDMETHOD(AdvancedAdd)(/*in*/int ipara1,/*[in]*/int ipara2,/*[out]*/int *pResult);
及其實現:
STDMETHODIMP CMath::AdvancedAdd(/*in*/int ipara1,/*[in]*/int ipara2,/*[out]*/int *pResult)
{
*pResult = ipara1 +ipara2;
cout<<"CMath::AdvancedAdd/n";
return S_OK;
}
6.建立localserver.exe
7.在目前的目錄下進入命令列。
執行命令:midl localserver.idl//這一步可以省略
執行命令:nmake -f LocalServerps.mk//效果是產生proxy_stub.dll//可能dll的名字不一樣這裡只是例子
執行命令:regsvr32.exe proxy_stub.dll//註冊存根代理dll
//.............
在以上的步驟中 :主要的就是加入介面和實現介面(組件)
同時註冊代理存根。
注意我們需要修改的檔案並不多!·!!!··
//////////////////////////////////////////////////////////
//。。。。。。。。。。。。
產生用戶端:
建立一個簡單的控制台程式:
#include "stdafx.h"
//下面兩個包含檔案的順序重要
#include "../LocalServer.h"
#include "../LocalServer_i.c"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
cout<<"in client:init com/n";
if(FAILED(::CoInitialize(NULL)) )//。。。。。。
{
cout<<"init com error /n";
return 0;
}
IMath *pm;
HRESULT hr;
hr = ::CoCreateInstance( CLSID_Math ,//。。。。。。。。。。
NULL,CLSCTX_LOCAL_SERVER, IID_IMath, (void **)&pm );
if ( FAILED(hr))
{
cout<<" get pimath error hr="<<hr<<"/n";
if ( hr== REGDB_E_CLASSNOTREG )
{
cout<<"REGDB_E_CLASSNOTREG "<<endl;
}
if ( hr ==CLASS_E_NOAGGREGATION)
{
cout<<"CLASS_E_NOAGGREGATION "<<endl;
}
::CoUninitialize();
return 0;
}
int rs=0;
pm->Add( 10 ,20 , &rs);
cout<<"result is :"<<rs<<endl;
IAdvancedMath *pam;
hr=pm->QueryInterface(IID_IAdvancedMath ,(void **)&pam);
if ( FAILED(hr))
{
cout<<" get pam error hr="<<hr<<"/n";
if ( hr== REGDB_E_CLASSNOTREG )
{
cout<<"REGDB_E_CLASSNOTREG "<<endl;
}
if ( hr ==CLASS_E_NOAGGREGATION)
{
cout<<"CLASS_E_NOAGGREGATION "<<endl;
}
pm->Release();
::CoUninitialize();
return 0;
}
pam->AdvancedAdd(50,100, &rs);
cout<<"result is :"<<rs<<endl;
pm->Release();
pam->Release();
::CoUninitialize();
return 0;
}
建立之後 直接運行用戶端就可以了。。
(如果伺服器還沒有啟動則, 用戶端會通過某種方式來讓伺服器啟動的。。)