一个模拟的COM示例程序
2007-11-17 20:55
288 查看
我认为这是《Visual
c++技术内幕》这本书中讲的最为出色的一个示例,将COM的“面向接口”的思路讲述得相当清晰,再加上嵌套类和引用计数的使用,让COM初学者能一窥其实质。
就我的理解,COM就好比是一瓶“胶水“,把客户exe同所需要的DLL或者其他exe”黏合“起来,而这些工作对客户来说是透明的,客户只是按双方协商好的协议,使用特定的接口就行了,只要接口保持不变,客户就不需要跟随DLL等的变化而变化,是为”面向接口“,这一切都是COM的功劳,而且COM使用包容和集合来代替继承,更加符合面向对象的思想。
// client.cpp
pseudo-OLE command-line application
Code
#include <stdio.h>
#include <stddef.h> // for offsetof in METHOD_PROLOGUE
#include <ASSERT.h>
#include "Interface.h"
#include "Spaceship.h"
CSpaceshipFactory g_factory;
//----------member functions-----------------------------------------
BOOL CSpaceshipFactory::ExternalQueryInterface(int nIid,void** ppvObj)
{
TRACE("7 Entering CSpaceshipFactory::ExternalQueryInterface--nIid = %d\n" ,nIid); //第7 步
switch (nIid)
{
case IID_IUnknown:
case IID_IClassFactory:
*ppvObj = &m_xClassFactory;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceshipFactory::XClassFactory::QueryInterface(int nIid,void** ppvObj)
{
TRACE("Entering CSpaceshipFactory::XClassFactory::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceshipFactory
}
BOOL CSpaceshipFactory::XClassFactory::CreateInstance(int nIid,void** ppvObj)
{
TRACE("8 Entering CSpaceshipFactory::XClassFactory::CreateInstance\n"); //第8 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
CSpaceship* pObj = new CSpaceship();
if (pObj->ExternalQueryInterface(nIid, ppvObj))
{
pObj->ExternalRelease(); // balance reference count
return TRUE;
}
return FALSE;
}
DWORD CSpaceshipFactory::XClassFactory::Release()
{
TRACE("37 Entering CSpaceshipFactory::XClassFactory::Release\n"); //第37 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceshipFactory::XClassFactory::AddRef()
{
TRACE("Entering CSpaceshipFactory::XClassFactory::AddRef\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
BOOL CSpaceship::ExternalQueryInterface(int nIid, void** ppvObj)
{
TRACE("17 20 22 Entering CSpaceship::ExternalQueryInterface--nIid = %d\n",nIid); //第17 步//第20 步//第22 步
switch (nIid)
{
case IID_IUnknown:
case IID_IMotion:
*ppvObj = &m_xMotion; // Both IMotion and IVisual are derived
break; // from IUnknown, so either pointer will do
case IID_IVisual:
*ppvObj = &m_xVisual;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceship::XMotion::QueryInterface(int nIid, void** ppvObj) {
TRACE("19 21 Entering CSpaceship::XMotion::QueryInterface--nIid = %d\n", nIid); //第19 步//第21 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceship
}
DWORD CSpaceship::XMotion::Release() {
TRACE("39 41 Entering CSpaceship::XMotion::Release\n"); //第39 步//第41 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XMotion::AddRef() {
TRACE("Entering CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XMotion::Fly() {
TRACE("24 Entering CSpaceship::XMotion::Fly\n"); //第24 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("25 this = %p, pThis = %p\n", this, pThis); //第25 步
TRACE("26 m_nPosition = %d\n", pThis->m_nPosition); //第26 步
TRACE("27 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第27 步
}
int& CSpaceship::XMotion::GetPosition() {
TRACE("28 Entering CSpaceship::XMotion::GetPosition\n"); //第28 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("29 this = %p, pThis = %p\n", this, pThis); //第29 步
TRACE("30 m_nPosition = %d\n", pThis->m_nPosition); //第30 步
TRACE("31 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第31 步
return pThis->m_nPosition;
}
BOOL CSpaceship::XVisual::QueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::XVisual::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to
// CSpaceship
}
DWORD CSpaceship::XVisual::Release() {
TRACE("43 Entering CSpaceship::XVisual::Release\n"); //第43 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XVisual::AddRef() {
TRACE("Entering CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XVisual::Display() {
TRACE("33 Entering CSpaceship::XVisual::Display\n"); //第33 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
TRACE("34 this = %p, pThis = %p\n", this, pThis); //第34 步
TRACE("35 m_nPosition = %d\n", pThis->m_nPosition); //第35 步
TRACE("36 m_nColor = %d\n", pThis->m_nColor); //第36 步
}
//----------simulates COM component ----------------------------------
// In real COM, this would be DllGetClassObject, which would be called
// whenever a client called CoGetClassObject
BOOL GetClassObject(int nClsid, int nIid, void** ppvObj)
{
ASSERT(nClsid == CLSID_CSpaceship);
ASSERT((nIid == IID_IUnknown) || (nIid == IID_IClassFactory));
return g_factory.ExternalQueryInterface(nIid, ppvObj);
// refcount is 2, which prevents accidental deletion
}
c++技术内幕》这本书中讲的最为出色的一个示例,将COM的“面向接口”的思路讲述得相当清晰,再加上嵌套类和引用计数的使用,让COM初学者能一窥其实质。
就我的理解,COM就好比是一瓶“胶水“,把客户exe同所需要的DLL或者其他exe”黏合“起来,而这些工作对客户来说是透明的,客户只是按双方协商好的协议,使用特定的接口就行了,只要接口保持不变,客户就不需要跟随DLL等的变化而变化,是为”面向接口“,这一切都是COM的功劳,而且COM使用包容和集合来代替继承,更加符合面向对象的思想。
// client.cpp
pseudo-OLE command-line application
Code
#include <stdio.h>
#include <stddef.h> // for offsetof in METHOD_PROLOGUE
#include <ASSERT.h>
#include "Interface.h"
#include "Spaceship.h"
CSpaceshipFactory g_factory;
//----------member functions-----------------------------------------
BOOL CSpaceshipFactory::ExternalQueryInterface(int nIid,void** ppvObj)
{
TRACE("7 Entering CSpaceshipFactory::ExternalQueryInterface--nIid = %d\n" ,nIid); //第7 步
switch (nIid)
{
case IID_IUnknown:
case IID_IClassFactory:
*ppvObj = &m_xClassFactory;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceshipFactory::XClassFactory::QueryInterface(int nIid,void** ppvObj)
{
TRACE("Entering CSpaceshipFactory::XClassFactory::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceshipFactory
}
BOOL CSpaceshipFactory::XClassFactory::CreateInstance(int nIid,void** ppvObj)
{
TRACE("8 Entering CSpaceshipFactory::XClassFactory::CreateInstance\n"); //第8 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
CSpaceship* pObj = new CSpaceship();
if (pObj->ExternalQueryInterface(nIid, ppvObj))
{
pObj->ExternalRelease(); // balance reference count
return TRUE;
}
return FALSE;
}
DWORD CSpaceshipFactory::XClassFactory::Release()
{
TRACE("37 Entering CSpaceshipFactory::XClassFactory::Release\n"); //第37 步
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceshipFactory::XClassFactory::AddRef()
{
TRACE("Entering CSpaceshipFactory::XClassFactory::AddRef\n");
METHOD_PROLOGUE(CSpaceshipFactory, ClassFactory) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
BOOL CSpaceship::ExternalQueryInterface(int nIid, void** ppvObj)
{
TRACE("17 20 22 Entering CSpaceship::ExternalQueryInterface--nIid = %d\n",nIid); //第17 步//第20 步//第22 步
switch (nIid)
{
case IID_IUnknown:
case IID_IMotion:
*ppvObj = &m_xMotion; // Both IMotion and IVisual are derived
break; // from IUnknown, so either pointer will do
case IID_IVisual:
*ppvObj = &m_xVisual;
break;
default:
*ppvObj = NULL;
return FALSE;
}
ExternalAddRef();
return TRUE;
}
BOOL CSpaceship::XMotion::QueryInterface(int nIid, void** ppvObj) {
TRACE("19 21 Entering CSpaceship::XMotion::QueryInterface--nIid = %d\n", nIid); //第19 步//第21 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to CSpaceship
}
DWORD CSpaceship::XMotion::Release() {
TRACE("39 41 Entering CSpaceship::XMotion::Release\n"); //第39 步//第41 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XMotion::AddRef() {
TRACE("Entering CSpaceship::XMotion::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XMotion::Fly() {
TRACE("24 Entering CSpaceship::XMotion::Fly\n"); //第24 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("25 this = %p, pThis = %p\n", this, pThis); //第25 步
TRACE("26 m_nPosition = %d\n", pThis->m_nPosition); //第26 步
TRACE("27 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第27 步
}
int& CSpaceship::XMotion::GetPosition() {
TRACE("28 Entering CSpaceship::XMotion::GetPosition\n"); //第28 步
METHOD_PROLOGUE(CSpaceship, Motion) // makes pThis
TRACE("29 this = %p, pThis = %p\n", this, pThis); //第29 步
TRACE("30 m_nPosition = %d\n", pThis->m_nPosition); //第30 步
TRACE("31 m_nAcceleration = %d\n", pThis->m_nAcceleration);//第31 步
return pThis->m_nPosition;
}
BOOL CSpaceship::XVisual::QueryInterface(int nIid, void** ppvObj) {
TRACE("Entering CSpaceship::XVisual::QueryInterface--nIid = %d\n", nIid);
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalQueryInterface(nIid, ppvObj); // delegate to
// CSpaceship
}
DWORD CSpaceship::XVisual::Release() {
TRACE("43 Entering CSpaceship::XVisual::Release\n"); //第43 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalRelease(); // delegate to CSimulatedCmdTarget
}
DWORD CSpaceship::XVisual::AddRef() {
TRACE("Entering CSpaceship::XVisual::AddRef\n");
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
return pThis->ExternalAddRef(); // delegate to CSimulatedCmdTarget
}
void CSpaceship::XVisual::Display() {
TRACE("33 Entering CSpaceship::XVisual::Display\n"); //第33 步
METHOD_PROLOGUE(CSpaceship, Visual) // makes pThis
TRACE("34 this = %p, pThis = %p\n", this, pThis); //第34 步
TRACE("35 m_nPosition = %d\n", pThis->m_nPosition); //第35 步
TRACE("36 m_nColor = %d\n", pThis->m_nColor); //第36 步
}
//----------simulates COM component ----------------------------------
// In real COM, this would be DllGetClassObject, which would be called
// whenever a client called CoGetClassObject
BOOL GetClassObject(int nClsid, int nIid, void** ppvObj)
{
ASSERT(nClsid == CLSID_CSpaceship);
ASSERT((nIid == IID_IUnknown) || (nIid == IID_IClassFactory));
return g_factory.ExternalQueryInterface(nIid, ppvObj);
// refcount is 2, which prevents accidental deletion
}
相关文章推荐
- 一个模拟的COM示例程序
- 一个COM示例程序
- 一个COM示例程序
- 小程序大问题,MSDN中一个小小示例所带来的疑问,一个关于DataList的一个简单应用
- 一个简单的jms点对点示例程序
- 一个模拟"显示桌面.scf"程序的JS小函数
- HR--一个奖金模拟试算的程序,仅供参考
- WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构
- 使用myeclipse集成struts,hibernate,spring的一个示例程序(转)
- Unity3D技术之用程序生成网格几何体-示例–创建一个广告牌
- 一个模拟金山毒霸等软件查毒过程的小程序
- 安卓第二天————模拟一个打电话程序
- 使用IAR embedded workbench for MCS-51编写的一个示例程序
- 通过一个模拟程序让你明白WCF大致的执行流程
- 模拟实现一个ATM + 购物商城程序
- 使用.bat文件运行Java程序的一个示例
- 一个简单的模拟车场的程序
- 一个简单的MD5加密算法C语言示例程序
- Sys请教下如何用C#开发一个简易的电路模拟程序<qi>
- 使用myeclipse集成struts,hibernate,spring的一个示例程序