COM学习笔记(三):动态链接(code)

本文是COM学习笔记的第三部分,主要探讨COM技术中的动态链接机制。通过示例代码client.cpp,展示了如何在客户端实现与COM组件的交互,揭示了COM动态链接的关键步骤和原理。
动态链接:
//从DLL中输出函数Create.h:
extern "C" IUnknown* CreateInstance(){
IUnknown* pI = (IUnknown*)(void*)new CA;
pI->AddRef();
return pI;
}
//cmpnt1.def
;
; Compnt1 module-defineition filel
;
LIBRARY Compnt1.dll
DESCRIPTION '(c)2014-2015 kai'
EXPORTS CreateInstance @1 PRIVATE
//DLL的装载:create.cpp
#include <iostream.h>
#include <unknown.h>
#include "Create.h"
typedef IUnknown* (*CREATEFUNCPTR)();
IUnknown* CallCreateInstance(char* name){
HINSTANCE hComponent = ::LoadLibrary(name);
if(hComponent == NULL){
cout<<"Error\n";
return NULL;
}
CREATEFUNCPTR CreateInstance=
(CREATEFUNCPTR)::GetProcAddress(hComponent,"CreateInstance");
if(CREATEFUNCPTR == NULL){
cout<<"Error"<<endl;
return NULL;
}
return CreateInstance();
}
?为什么可以使用DLL来实现组件呢?其原因在于DLL可以共享它们所链入的应用程序的地址空间。

//客户的实现代码:client.cpp

#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Create.h"
void trace(const char* msg){cout<<"Client 1:\t"<<msg<<endl;}
int main(){
HRESULT hr;
char name[40];
cout<<"Enter the filename of a component to use [Cmpnt?.dll]";
cin>>name;
cout<<endl;
trace("Get an IUnknown pointer.");
IUnknown* pIUnknown = CallCreateInstance(name);
if(pIUnknown == NULL){
trace("CallCreateInstance Failed.");
return 1;
}
trace("Get interface IX.");
IX* pIX = NULL;
hr = pIUnknown->QuaryInterface(IID_IX,(void**)&pIX);
if(SUCCEEDED(hr)){
trace("Succeeded getting IX.");
pIX->Fx();
pIX->Release();
}
else{
trace("Could not get interface IX.");
}
trace("Release IUnknown interface.");
pIUnknown->Release();
return 0;
}
//实现组建的代码cmpnt1.cpp
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
void trace(const char* msg){cout<<"Component 1: \t"<<msg<<endl;}
class CA : public IX
{
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual void __stdcall Fx(){cout<<"Fx"<<endl;}
public:
CA():m_cRef(0){}
~CA(){trace("Destroy self.");}
private:
long m_cRef;
};
HRESULT __stdcall CA::QueryInterface(const IID& iid,void** ppv){
if(iif == IID_IUnknown){
trace("Return pointer to IUnknown.");
*ppv = static_cast<IX*>(this);
}
else if(iid == IID_IX){
trace("Return pointer to IX.");
*ppv = static_cast<IX*>(this);
}
else{
trace("Interface not supported.");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef(){
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CA::Release(){
if(InterlockedDecrement(&m_cRef)==0){
delete this;
return 0;
}
return m_cRef;
}
extern "C" IUnknown* CreateInstance(){
IUnknown* pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}
//在IFACE.H中声明了客户和组件所使用的所有接口:
interface IX : IUnknown{
virtual void __stdcall Fx() =  0;
};
interface IY : IUnknown{
virtual void __stdcall Fy() = 0;
};
interface IZ : IUnknown{
virtual void __stdcall Fz() = 0;
};
extern "C"{
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
}
//这些接口ID的定义在文件GUIDS.CPP中:
#include <Objbase.h>
extern "C"{
static const IID IID_IX = {0x32bb8320,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};

static const IID IID_IY = {0x32bb8321,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};

static const IID IID _IZ =  {0x32bb8322,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值