ATL(Active Template Library,活动模板库)使用c++模板作为自己的实现的基本特性。模板分为两种:函数模板和类模板。
一. ATL如何使用模板
以下例子并没有涉及真正的ATL类,只是展示ATL如何使用模板计数在基类里访问成员函数。首先我们看下面的两个类:
class CBase { public: CBase(){} ~CBase(){} void BaseMethod() { cout << "BaseMethod in Base" << endl; } }; class CMath : public CBase { public: CMath(){} ~CMath(){} };
CMath类本身没有任何方法,但它继承了Cbase类的BaseMethod方法。
下面我们就来看看CComObject类是如何根据ATL的类实现进行构建的。
template<class T> class CComObject : public T { public: CComObject(){} ~CComObject(){} void CallBaseMethod() { T *pT = static_cast<T*> (this); //就是这句关键的转换 pT->BaseMethod(); } };
通过把基类作为一个模板参数进行传递并使用该类型对类实现指针进行类型转换,就可以得到指向基类实现的一个直接指针。
下面我们利用ATL来实现一个组件。ATL模板已经帮你实现了类厂,注册,你只需要专注组件的创建。
(1)打开vs2010--->选择ATL,命名为Chapter3_Server->选择宿主为DLL。
(2) 然后点击工程右键--->Add-->class。添加接口IMyMath。注意将属性改为custome,不要选择dual.
(3)然后到MyMath.cpp中实现接口函数。
(4)然后我们再添加一个接口IAdvancedMath,只能手动添加。
v4.1 首先在chapter3_server.idl中修改如下:
// Chapter3_Server.idl : IDL source for Chapter3_Server // // This file will be processed by the MIDL tool to // produce the type library (Chapter3_Server.tlb) and marshalling code. import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(3C88BDD5-D63E-49B8-9472-CDD02A1142F3), pointer_default(unique) ] interface IMyMath : IUnknown{ [] HRESULT Add([in] LONG lOp1, [in] LONG lOp2, [out] LONG* lpResult); [] HRESULT Sub([in] LONG lOp1, [in] LONG lOp2, [out] LONG* lpResult); [] HRESULT Mul([in] LONG lOp1, [in] LONG lOp2, [out] LONG* lpResult); [] HRESULT Div([in] LONG lOp1, [in] LONG lOp2, [out] LONG* lpResult); }; [ object, uuid(C5747916-8A10-411D-999F-FF0DE103D8D9), helpstring("IAdvancedMath Interface"), pointer_default(unique) ] interface IAdvancedMath : IUnknown{ [] HRESULT Factorial( [in] short sFact,[out,retval] long* pResult ); [] HRESULT Fibonacci( [in] short sFib, [out,retval] long* pResult); }; [ uuid(940F5ED1-F1EF-4BE9-8729-A03D70105738), version(1.0), ] library Chapter3_ServerLib { importlib("stdole2.tlb"); [ uuid(7EEEE9E3-FADD-44E2-86EE-D25C6CD902ED) ] coclass MyMath { [default] interface IMyMath; interface IAdvancedMath; }; };
v4.2 到 MyMath.h头文件中修改如下:
// MyMath.h : Declaration of the CMyMath #pragma once #include "resource.h" // main symbols #include "Chapter3_Server_i.h" #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." #endif using namespace ATL; // CMyMath class ATL_NO_VTABLE CMyMath : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyMath, &CLSID_MyMath>, public IMyMath, public IAdvancedMath { public: CMyMath() { } DECLARE_REGISTRY_RESOURCEID(IDR_MYMATH) BEGIN_COM_MAP(CMyMath) COM_INTERFACE_ENTRY(IMyMath) COM_INTERFACE_ENTRY(IAdvancedMath) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } //IMath public: STDMETHOD(Add)(LONG lOp1, LONG lOp2, LONG* lpResult); STDMETHOD(Sub)(LONG lOp1, LONG lOp2, LONG* lpResult); STDMETHOD(Mul)(LONG lOp1, LONG lOp2, LONG* lpResult); STDMETHOD(Div)(LONG lOp1, LONG lOp2, LONG* lpResult); //IAdvancedMath public: STDMETHOD(Factorial)(short,long*); STDMETHOD(Fibonacci)(short,long*); }; OBJECT_ENTRY_AUTO(__uuidof(MyMath), CMyMath)
v4.3 到MyMath.cpp中实现函数
// MyMath.cpp : Implementation of CMyMath #include "stdafx.h" #include "MyMath.h" // CMyMath STDMETHODIMP CMyMath::Add(LONG lOp1, LONG lOp2, LONG* lpResult) { // TODO: Add your implementation code here *lpResult = lOp1 + lOp2; return S_OK; } STDMETHODIMP CMyMath::Sub(LONG lOp1, LONG lOp2, LONG* lpResult) { // TODO: Add your implementation code here *lpResult = lOp1 - lOp2; return S_OK; } STDMETHODIMP CMyMath::Mul(LONG lOp1, LONG lOp2, LONG* lpResult) { // TODO: Add your implementation code here *lpResult = lOp1 * lOp2; return S_OK; } STDMETHODIMP CMyMath::Div(LONG lOp1, LONG lOp2, LONG* lpResult) { // TODO: Add your implementation code here *lpResult = lOp1 / lOp2; return S_OK; } long calcFibonacci(short n) { if( n <= 1 ) return 1; return calcFibonacci(n-1) + calcFibonacci(n-2); } long calcFactorial(short n) { if( n > 1 ) return n * calcFactorial(n-1); else return 1; } STDMETHODIMP CMyMath::Factorial(short sOp,long* pResult) { *pResult = calcFactorial(sOp); return S_OK; } STDMETHODIMP CMyMath::Fibonacci(short sOp,long* pResult) { *pResult = calcFibonacci(sOp); return S_OK; }
编译即可。
然后利用regsvr32进行注册。
下面我们编写win32测试函数。
// TestChapter3.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <tchar.h> #include <InitGuid.h> #include "..\..\Chapter3_Server\Chapter3_Server\Chapter3_Server_i.c" #include "..\..\Chapter3_Server\Chapter3_Server\Chapter3_Server_i.h" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { cout << "初始化com" << endl; if( FAILED(CoInitialize(NULL)) ) { cout << "com初始化失败" << endl; return -1; } IMyMath* pMath; HRESULT hr = CoCreateInstance( CLSID_MyMath, NULL, CLSCTX_INPROC, IID_IMyMath, (void**)&pMath); if( FAILED(hr) ) { cout.setf(ios::hex,ios::basefield); cout << "Failed to Create server instance. HR =" << hr << endl; } cout << "get IMyMath interface succeed!" << endl; long result; pMath->Mul(100,8,&result); cout << "100*8=" << result << endl; IAdvancedMath* pAdvMath = NULL; hr = pMath->QueryInterface(IID_IAdvancedMath,(void**)&pAdvMath); if( FAILED(hr) ) { cout << "QueryInterface for IAdvancedMath failed" << endl; pMath->Release(); CoUninitialize(); return -1; } cout << "get IAdvancedMath interface succeed!" << endl; pAdvMath->Factorial(10,&result); cout << "10!=" << result << endl; pAdvMath->Fibonacci(10,&result); cout << "Fibo(10)=" << result << endl; pMath->Release(); pAdvMath->Release(); CoUninitialize(); return 0; }