Programming 版 (精华区)
发信人: quest (1234), 信区: Programming
标 题: 循循渐进COM指南
发信站: 哈工大紫丁香 (2001年07月26日09:07:57 星期四), 转信
循循渐进COM指南
刘峰
介绍
我认为每一个希望能理解COM背后的基本原理程序员,都必须至少用一般的C++语言写
一个简单的COM对象,也就是在没有MFC/ATL等模板和宏的帮助下完成一个COM对象。在这
篇文章里,我将介绍一个从最初的原理来建立一个COM对象的指导方针。该组件能被
VC/VB客户程序使用。
作为一个练习,我们将设计一个COM组件,它实现了假定的非常快的加法运算。该组件接
收两个LONG类型的参数,给用户返回一个LONG类型的值,该值就是加法运算的结果。
接口
COM对象的接口不讨论实际的实现,但是该方法名将被另外的与该组件通讯的客户使
用。我们将我们的接口命名为Iadd。使用接口定义语言(IDL)声明该接口。在我们的接
口Iadd里,有两个被用做传递参数的方法SetFirstNumber和SetSecondNumber,而方法
DoTheAddition是实际完成加法运算和返回结果的。
第一步:
建立一个新的Win32 DLL项目(AddObjSay),新建一个空文件并键入下面的内容,将
其存为Iadd.idl。接口的标识符guid由工具guidgen.exe产生。
import "unknwn.idl";
[
object,
uuid(1221db62-f3d8-11d4-825d-00104b3646c0),
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;
}
第二步:
使用命令行编译工具MIDL.EXE编译文件Iadd.idl,将生成下列文件:
Iadd.H 包含C++风格的接口描述
Dlldata.c 包含代理DLL的代码,在离程组件中使用
Iadd.tlb 二进制文件,定义了IADD接口和它所有方法的格式。
Iadd_p.c 包含了代理DLL的汇集代码,在不同的进程/计算机间通讯时使用。
Iadd_i.h 包含了接口的IIDs.
第三步:
开始建立COM组件。建立一个新文件Addobj.H,声明一个从接口Iadd(Iadd.H)派生的
C++类,命名为CAddObj。切记,IAdd从IUnknown派生,同样也是一个抽象基类。因此,我
们必须为抽象类Iadd和Iunknown声明所有的方法。
///////////////////////////////////////////////////////////
//
//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
};
///////////////////////////////////////////////////////////
第四步:
提供接口Iadd所有的方法的具体实现。建立一个新文件(AddObj.CPP),并加入实现
代码:
///////////////////////////////////////////////////////////
//
//AddObj.cpp
//Contains the method implementations of the IAdd interface
//interfaces
//
#include <objbase.h>
#include "AddObj.h"
#include "IAdd_i.c"
HRESULT __stdcall CAddObj::SetFirstNumber( long nX1)
{
m_nX1=nX1;
if (m_bIsLogEnabled) WriteToLog("Junk");
return S_OK;
}
HRESULT __stdcall CAddObj::SetSecondNumber( long nX2)
{
m_nX2=nX2;
return S_OK;
}
HRESULT __stdcall CAddObj::DoTheAddition( long *pBuffer)
{
*pBuffer =m_nX1 + m_nX2;
return S_OK;
}
第五步:
Iunknown接口的方法也需要实现。我们将在同一个文件中实现三个方法(AddRef,
Release,QueryInterface)。私有成员变量m_nRefCount用来维护对象的生命周期,
m_nRefCount不能直接增加和减少,应用一个线程安全的方法,可以使用API函数
InterlockedIncrement 和InterlockedDecrement:
HRESULT __stdcall CAddObj::QueryInterface(
REFIID riid ,
void **ppObj)
{
if (riid == IID_IUnknown)
{
*ppObj = static_cast(this) ;
AddRef() ;
return S_OK;
}
if (riid == IID_IAdd)
{
*ppObj = static_cast(this) ;
AddRef() ;
return S_OK;
}
//
//if control reaches here then , let the client know that
//we do not satisfy the required interface
//
*ppObj = NULL ;
return E_NOINTERFACE ;
}//QueryInterface method
ULONG __stdcall CAddObj::AddRef()
{
return InterlockedIncrement(&m_nRefCount) ;
}
ULONG __stdcall CAddObj::Release()
{
long nRefCount=0;
nRefCount=InterlockedDecrement(&m_nRefCount) ;
if (nRefCount == 0) delete this;
return nRefCount;
}
第六步:
我们已经完成了该COM组件的功能部分。作为一个COM组件,每个COM对象还必须实现
一个特殊的接口IclassFactory。客户程序通过该接口得到一个组件对象的实例。类厂接
口IclassFactory和其他接口一样,也必须从Iunkonwn接口派生。建立一个新文件(
Addobjfactory.cpp),声明一个从接口IclassFactory派生的类CaddFactory:
///////////////////////////////////////////////////////////
//
//AddObjFactory.h
//Contains the C++ class declarations for the IClassFactory implementations
//
class CAddFactory : public IClassFactory
{
public:
//interface IUnknown methods
HRESULT __stdcall QueryInterface(
REFIID riid ,
void **ppObj);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//interface IClassFactory methods
HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv) ;
HRESULT __stdcall LockServer(BOOL bLock) ;
private:
long m_nRefCount;
};
第七步:
实现CaddFactory中的方法,建立一个新文件(Addobjfactory.cpp),实现
IclassFactory和Iunknown中的所有方法,其中AddRef,Release,QueryInterface的实现
类似CaddObj。方法CreateInstanc是用来实例化CaddObj和返回接口指针的。而方法
LoakServer在此没有给出具体的实现。
HRESULT __stdcall CAddFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
//
//This method lets the client manufacture components en masse
//The class factory provides a mechanism to control the way
//the component is created. Within the class factory the
//author of the component may decide to selectivey enable
//or disable creation as per license agreements
//
//
// Cannot aggregate.
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION ;
}
//
// Create an instance of the component.
//
CAddObj* pObject = new CAddObj ;
if (pObject == NULL)
{
return E_OUTOFMEMORY ;
}
//
// Get the requested interface.
//
return pObject->QueryInterface(iid, ppv) ;
}
HRESULT __stdcall CAddFactory::LockServer(BOOL bLock)
{
return E_NOTIMPL;
}
第八步:
一个在程COM组件仅仅是一个简单的WIN32 DLL。每个COM DLL必须有一个输出函数
DllGetClassObject。客户程序调用该函数得到一个类厂的实例(Iunknow或
IClassFactory)。建立一个新文件(Exports.Cpp)实现该函数。
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
//
//Check if the requested COM object is implemented in this DLL
//There can be more than 1 COM object implemented in a DLL
//
if (clsid == CLSID_AddObject)
{
//
//iid specifies the requested interface for the factory object
//The client can request for IUnknown, IClassFactory,
//IClassFactory2
//
CAddFactory *pAddFact = new CAddFactory;
if (pAddFact == NULL)
return E_OUTOFMEMORY;
else
{
return pAddFact->QueryInterface(iid , ppv);
}
}
//
//if control reaches here then that implies that the object
//specified by the user is not implemented in this DLL
//
return CLASS_E_CLASSNOTAVAILABLE;
}
第九步:
当COM DLL从内存卸载时,客户程序应该知道。一个在程组件可以通过调用API函数
LoadLibrary显示将DLL加载到客户进程空间,可以调用FreeLibrary卸载DLL。
COM DLL安全卸载时客户程序必须知道。客户程序必须确认没有该组件对象的实例存
在。我们将在COM DLL中加入一个全局变量g_nComObjsInUse,并在CaddObj和
CaddFactory的构造函数中对该变量执行增量操作,同样,在他们对应的析构函数中进行
减量操作。
我们需要输出另一个特殊函数DllCanUnloadNow,具体实现如下:
STDAPI DllCanUnloadNow()
{
//
//A DLL is no longer in use when it is not managing any existing objects
// (the reference count on all of its objects is 0).
//We will examine the value of g_nComObjsInUse
//
if (g_nComObjsInUse == 0)
{
return S_OK;
}
else
{
return S_FALSE;
}
}
第十步:
一个COM对象的位置信息必须加入注册表中。这可以通过建立一个外部的.REG文件或
创建一个DLL输出函数DllRegisterServer来实现。为了从注册表中删除该信息,我们需要
一个输出函数DllUnregisterServer。这两个函数的实现在文件Registry.Cpp中,工具
Regsve32.exe可以用来加载DLL并执行DllRegisterServer和DllUnregisterServer。
为了输出上述4个函数,我们需要建立.DEF文件如下:
;contains the list of functions that are being exported from this DLL
DESCRIPTION "Simple COM object"
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
第十一步:
将文件Iadd.idl加入项目的工作区中:
为该项目建立定制选项:
为了在每次建立后执行Regsvr32.exe在”Post-build step”对话框中加入一个命令行:
建立该DLL。
第十二步:
从VB中使用该COM组件,建立一个简单的EXE项目,执行下面几行代码即可。
Dim iAdd As CodeGuruMathLib.iAdd
Set iAdd = CreateObject("CodeGuru.FastAddition")
iAdd.SetFirstNumber 100
iAdd.SetSecondNumber 200
MsgBox "total = " & iAdd.DoTheAddition()
第十三步:
我们所用到的文件如下:
IAdd.idl 接口声明
AddObj.h CaddObj类的声明
AddObjFactory.h CaddFactory类的声明
AddObj.cpp CaddObj的具体实现
AddObj.cpp CaddFactory的具体实现
Exports.cpp DllGetClassObject,DllCanUnloadNow 和 DllMain的实现
Registry.cpp DllRegisterServer,DllUnregisterServer的实现
AddObjGuid.h AddObj COM对象的GUID
第十四步:
类型库随同Addobj.Dll一起发布。简单的处理是,将类型库Iadd.tbl作为一个二进制
资源加入到AddObj.Dll中。这样,我们只需要将DLL发布给客户即可。
第十五步:
一个Visual C++用户可以通过下列几步使用该组件:
1、#import “iadd.lib”
2、#include “iadd.h”
3、编写客户程序。
//
///Client.cpp
//
//Demo of client using the COM object from AddObj.dll
//
#include <objbase.h>
#include <stdio.h>
#import "AddObj.dll"
//
//Here we do a #import on the DLL ,you can also do a #import on the .TLB
//The #import directive generates two files (.tlh/.tli) in the output
folders.
//
void main()
{
long n1 =100, n2=200;
long nOutPut = 0;
CoInitialize(NULL);
CodeGuruMathLib::IAddPtr pFastAddAlgorithm;
//
//IAddPtr is not the actual interface IAdd, but a template C++ class
(_com_ptr_t)
//that contains an embedded instance of the raw IAdd pointer
//While destructing , the destructor makes sure to invoke Release() on the
internal
//raw interface pointer. Further, the operator -> has been overloaded to
direct all
//method invocations to the internal raw interface pointer.
//
pFastAddAlgorithm.CreateInstance("CodeGuru.FastAddition");
pFastAddAlgorithm->SetFirstNumber(n1);//"->" overloading in action
pFastAddAlgorithm->SetSecondNumber(n2);
nOutPut = pFastAddAlgorithm->DoTheAddition();
printf("\nOutput after adding %d & %d is %d\n",n1,n2,nOutPut);
}
循循渐进COM指南
刘峰
介绍
我认为每一个希望能理解COM背后的基本原理程序员,都必须至少用一般的C++语言写
一个简单的COM对象,也就是在没有MFC/ATL等模板和宏的帮助下完成一个COM对象。在这
篇文章里,我将介绍一个从最初的原理来建立一个COM对象的指导方针。该组件能被
VC/VB客户程序使用。
作为一个练习,我们将设计一个COM组件,它实现了假定的非常快的加法运算。该组件接
收两个LONG类型的参数,给用户返回一个LONG类型的值,该值就是加法运算的结果。
接口
COM对象的接口不讨论实际的实现,但是该方法名将被另外的与该组件通讯的客户使
用。我们将我们的接口命名为Iadd。使用接口定义语言(IDL)声明该接口。在我们的接
口Iadd里,有两个被用做传递参数的方法SetFirstNumber和SetSecondNumber,而方法
DoTheAddition是实际完成加法运算和返回结果的。
第一步:
建立一个新的Win32 DLL项目(AddObjSay),新建一个空文件并键入下面的内容,将
其存为Iadd.idl。接口的标识符guid由工具guidgen.exe产生。
import "unknwn.idl";
[
object,
uuid(1221db62-f3d8-11d4-825d-00104b3646c0),
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;
}
第二步:
使用命令行编译工具MIDL.EXE编译文件Iadd.idl,将生成下列文件:
Iadd.H 包含C++风格的接口描述
Dlldata.c 包含代理DLL的代码,在离程组件中使用
Iadd.tlb 二进制文件,定义了IADD接口和它所有方法的格式。
Iadd_p.c 包含了代理DLL的汇集代码,在不同的进程/计算机间通讯时使用。
Iadd_i.h 包含了接口的IIDs.
第三步:
开始建立COM组件。建立一个新文件Addobj.H,声明一个从接口Iadd(Iadd.H)派生的
C++类,命名为CAddObj。切记,IAdd从IUnknown派生,同样也是一个抽象基类。因此,我
们必须为抽象类Iadd和Iunknown声明所有的方法。
///////////////////////////////////////////////////////////
//
//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
};
///////////////////////////////////////////////////////////
第四步:
提供接口Iadd所有的方法的具体实现。建立一个新文件(AddObj.CPP),并加入实现
代码:
///////////////////////////////////////////////////////////
//
//AddObj.cpp
//Contains the method implementations of the IAdd interface
//interfaces
//
#include <objbase.h>
#include "AddObj.h"
#include "IAdd_i.c"
HRESULT __stdcall CAddObj::SetFirstNumber( long nX1)
{
m_nX1=nX1;
if (m_bIsLogEnabled) WriteToLog("Junk");
return S_OK;
}
HRESULT __stdcall CAddObj::SetSecondNumber( long nX2)
{
m_nX2=nX2;
return S_OK;
}
HRESULT __stdcall CAddObj::DoTheAddition( long *pBuffer)
{
*pBuffer =m_nX1 + m_nX2;
return S_OK;
}
第五步:
Iunknown接口的方法也需要实现。我们将在同一个文件中实现三个方法(AddRef,
Release,QueryInterface)。私有成员变量m_nRefCount用来维护对象的生命周期,
m_nRefCount不能直接增加和减少,应用一个线程安全的方法,可以使用API函数
InterlockedIncrement 和InterlockedDecrement:
HRESULT __stdcall CAddObj::QueryInterface(
REFIID riid ,
void **ppObj)
{
if (riid == IID_IUnknown)
{
*ppObj = static_cast(this) ;
AddRef() ;
return S_OK;
}
if (riid == IID_IAdd)
{
*ppObj = static_cast(this) ;
AddRef() ;
return S_OK;
}
//
//if control reaches here then , let the client know that
//we do not satisfy the required interface
//
*ppObj = NULL ;
return E_NOINTERFACE ;
}//QueryInterface method
ULONG __stdcall CAddObj::AddRef()
{
return InterlockedIncrement(&m_nRefCount) ;
}
ULONG __stdcall CAddObj::Release()
{
long nRefCount=0;
nRefCount=InterlockedDecrement(&m_nRefCount) ;
if (nRefCount == 0) delete this;
return nRefCount;
}
第六步:
我们已经完成了该COM组件的功能部分。作为一个COM组件,每个COM对象还必须实现
一个特殊的接口IclassFactory。客户程序通过该接口得到一个组件对象的实例。类厂接
口IclassFactory和其他接口一样,也必须从Iunkonwn接口派生。建立一个新文件(
Addobjfactory.cpp),声明一个从接口IclassFactory派生的类CaddFactory:
///////////////////////////////////////////////////////////
//
//AddObjFactory.h
//Contains the C++ class declarations for the IClassFactory implementations
//
class CAddFactory : public IClassFactory
{
public:
//interface IUnknown methods
HRESULT __stdcall QueryInterface(
REFIID riid ,
void **ppObj);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//interface IClassFactory methods
HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv) ;
HRESULT __stdcall LockServer(BOOL bLock) ;
private:
long m_nRefCount;
};
第七步:
实现CaddFactory中的方法,建立一个新文件(Addobjfactory.cpp),实现
IclassFactory和Iunknown中的所有方法,其中AddRef,Release,QueryInterface的实现
类似CaddObj。方法CreateInstanc是用来实例化CaddObj和返回接口指针的。而方法
LoakServer在此没有给出具体的实现。
HRESULT __stdcall CAddFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
//
//This method lets the client manufacture components en masse
//The class factory provides a mechanism to control the way
//the component is created. Within the class factory the
//author of the component may decide to selectivey enable
//or disable creation as per license agreements
//
//
// Cannot aggregate.
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION ;
}
//
// Create an instance of the component.
//
CAddObj* pObject = new CAddObj ;
if (pObject == NULL)
{
return E_OUTOFMEMORY ;
}
//
// Get the requested interface.
//
return pObject->QueryInterface(iid, ppv) ;
}
HRESULT __stdcall CAddFactory::LockServer(BOOL bLock)
{
return E_NOTIMPL;
}
第八步:
一个在程COM组件仅仅是一个简单的WIN32 DLL。每个COM DLL必须有一个输出函数
DllGetClassObject。客户程序调用该函数得到一个类厂的实例(Iunknow或
IClassFactory)。建立一个新文件(Exports.Cpp)实现该函数。
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
//
//Check if the requested COM object is implemented in this DLL
//There can be more than 1 COM object implemented in a DLL
//
if (clsid == CLSID_AddObject)
{
//
//iid specifies the requested interface for the factory object
//The client can request for IUnknown, IClassFactory,
//IClassFactory2
//
CAddFactory *pAddFact = new CAddFactory;
if (pAddFact == NULL)
return E_OUTOFMEMORY;
else
{
return pAddFact->QueryInterface(iid , ppv);
}
}
//
//if control reaches here then that implies that the object
//specified by the user is not implemented in this DLL
//
return CLASS_E_CLASSNOTAVAILABLE;
}
第九步:
当COM DLL从内存卸载时,客户程序应该知道。一个在程组件可以通过调用API函数
LoadLibrary显示将DLL加载到客户进程空间,可以调用FreeLibrary卸载DLL。
COM DLL安全卸载时客户程序必须知道。客户程序必须确认没有该组件对象的实例存
在。我们将在COM DLL中加入一个全局变量g_nComObjsInUse,并在CaddObj和
CaddFactory的构造函数中对该变量执行增量操作,同样,在他们对应的析构函数中进行
减量操作。
我们需要输出另一个特殊函数DllCanUnloadNow,具体实现如下:
STDAPI DllCanUnloadNow()
{
//
//A DLL is no longer in use when it is not managing any existing objects
// (the reference count on all of its objects is 0).
//We will examine the value of g_nComObjsInUse
//
if (g_nComObjsInUse == 0)
{
return S_OK;
}
else
{
return S_FALSE;
}
}
第十步:
一个COM对象的位置信息必须加入注册表中。这可以通过建立一个外部的.REG文件或
创建一个DLL输出函数DllRegisterServer来实现。为了从注册表中删除该信息,我们需要
一个输出函数DllUnregisterServer。这两个函数的实现在文件Registry.Cpp中,工具
Regsve32.exe可以用来加载DLL并执行DllRegisterServer和DllUnregisterServer。
为了输出上述4个函数,我们需要建立.DEF文件如下:
;contains the list of functions that are being exported from this DLL
DESCRIPTION "Simple COM object"
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
第十一步:
将文件Iadd.idl加入项目的工作区中:
为该项目建立定制选项:
为了在每次建立后执行Regsvr32.exe在”Post-build step”对话框中加入一个命令行:
建立该DLL。
第十二步:
从VB中使用该COM组件,建立一个简单的EXE项目,执行下面几行代码即可。
Dim iAdd As CodeGuruMathLib.iAdd
Set iAdd = CreateObject("CodeGuru.FastAddition")
iAdd.SetFirstNumber 100
iAdd.SetSecondNumber 200
MsgBox "total = " & iAdd.DoTheAddition()
第十三步:
我们所用到的文件如下:
IAdd.idl 接口声明
AddObj.h CaddObj类的声明
AddObjFactory.h CaddFactory类的声明
AddObj.cpp CaddObj的具体实现
AddObj.cpp CaddFactory的具体实现
Exports.cpp DllGetClassObject,DllCanUnloadNow 和 DllMain的实现
Registry.cpp DllRegisterServer,DllUnregisterServer的实现
AddObjGuid.h AddObj COM对象的GUID
第十四步:
类型库随同Addobj.Dll一起发布。简单的处理是,将类型库Iadd.tbl作为一个二进制
资源加入到AddObj.Dll中。这样,我们只需要将DLL发布给客户即可。
第十五步:
一个Visual C++用户可以通过下列几步使用该组件:
1、#import “iadd.lib”
2、#include “iadd.h”
3、编写客户程序。
//
///Client.cpp
//
//Demo of client using the COM object from AddObj.dll
//
#include <objbase.h>
#include <stdio.h>
#import "AddObj.dll"
//
//Here we do a #import on the DLL ,you can also do a #import on the .TLB
//The #import directive generates two files (.tlh/.tli) in the output
folders.
//
void main()
{
long n1 =100, n2=200;
long nOutPut = 0;
CoInitialize(NULL);
CodeGuruMathLib::IAddPtr pFastAddAlgorithm;
//
//IAddPtr is not the actual interface IAdd, but a template C++ class
(_com_ptr_t)
//that contains an embedded instance of the raw IAdd pointer
//While destructing , the destructor makes sure to invoke Release() on the
internal
//raw interface pointer. Further, the operator -> has been overloaded to
direct all
//method invocations to the internal raw interface pointer.
//
pFastAddAlgorithm.CreateInstance("CodeGuru.FastAddition");
pFastAddAlgorithm->SetFirstNumber(n1);//"->" overloading in action
pFastAddAlgorithm->SetSecondNumber(n2);
nOutPut = pFastAddAlgorithm->DoTheAddition();
printf("\nOutput after adding %d & %d is %d\n",n1,n2,nOutPut);
}
--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: wpc.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:213.946毫秒