COM---动态链接

定义接口

//
// Iface.h
//

// 接口,所有COM接口都必须实现 IUnkown 接口
interface IX : IUnknown
{
    virtual void __stdcall Fx() = 0 ;
} ;

interface IY : IUnknown
{
    virtual void __stdcall Fy() = 0 ;
} ;

interface IZ : IUnknown
{
    virtual void __stdcall Fz() = 0 ;
} ;

// GUIDs 的前向引用
// extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字
// 告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
// IID:代表COM组件的接口
extern "C"
{
    extern const IID IID_IX ;
    extern const IID IID_IY ;
    extern const IID IID_IZ ;
}

定义组件, 从DLL中输出函数

//
// Cmpnt1.cpp
// 编译时, 使用: cl /LD Cmpnt1.cpp GUIDs.cpp UUID.lib Cmpnt1.def
//
#include <iostream.h>

//定义了 #define interface struct
#include <objbase.h>

#include "Iface.h"

void trace(const char* msg) 
{ 
    cout << "Component 1:\t" << msg << endl ;
}

//
// Component
//
class CA : public IX
{
    // 实现 IUnknown 接口
    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ;  
    virtual ULONG __stdcall AddRef() ;   
    virtual ULONG __stdcall Release() ;    

    // 实现 IX 接口
    virtual void __stdcall Fx() { cout << "Fx" << endl ;}

public:
    // 构造
    CA() : m_cRef(0) {}

    // 析构
    ~CA() { trace("Destroy self.") ;}

private:
    long m_cRef ;
} ;

//接口查询
//IID:代表COM组件的接口,所需接口的常量
//ppv: 存放所请求接口指针的地址
//HRESULT: 具有特定结构的32位值
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{   
    if (iid == 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 ;  //客户所查询的接口不被支持时,将ppv置为NULL
        return E_NOINTERFACE ;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef() ; 
    return S_OK ;
}

//引用计数加1
ULONG __stdcall CA::AddRef()
{
    return InterlockedIncrement(&m_cRef) ;
}

//引用计数减1
ULONG __stdcall CA::Release() 
{
    if (InterlockedDecrement(&m_cRef) == 0)
    {
        delete this ;
        return 0 ;
    }
    return m_cRef ;
}

//从DLL中输出该函数
//建立一个组件,并返回一个IUnknown指针
//extern "C" 以C语言的方式编译,防止C++编译器在函数名上加上类型信息
extern "C" IUnknown* CreateInstance()
{
    IUnknown* pI = static_cast<IX*>(new CA) ;
    pI->AddRef() ;
    return pI ;
}

定义DLL要输出的函数
Cmpnt1.def

;
; Cmpnt1 模块-定义 文件
; 告诉连接程序需要输出什么函数
; LIBRARY:加上DLL的实际名称
; EXPORTS:列出待从DLL中输出的函数的名称,对每个名称,还可加上一个序号

LIBRARY         Cmpnt1.dll
DESCRIPTION     '(c)1996-1997 Dale E. Rogerson'

EXPORTS
                CreateInstance @1   PRIVATE

DLL的装载

//
// Create.h
//

//name:DLL的名称
IUnknown* CallCreateInstance(char* name) ;
//
// Create.cpp 
//
#include <iostream.h>
#include <unknwn.h>    // 声明 IUnknown.

#include "Create.h"

typedef IUnknown* (*CREATEFUNCPTR)() ;

//name:所装载的DLL名称
IUnknown* CallCreateInstance(char* name)
{
    // 将动态链接库加载到进程中
    // 返回一个所装载的DLL名称句柄
    HINSTANCE hComponent = ::LoadLibrary(name) ;
    if (hComponent == NULL)
    {
        cout << "CallCreateInstance:\tError: Cannot load component." << endl ;
        return NULL ;
    }

    // 得到 CreateInstance 函数的地址
    // hComponent:DLL的句柄
    // "CreateInstance":函数的名称
    CREATEFUNCPTR CreateInstance 
        = (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance") ;
    if (CreateInstance == NULL)
    {
        cout  << "CallCreateInstance:\tError: "
              << "Cannot find CreateInstance function."
              << endl ;
        return NULL ;
    }

    return CreateInstance() ;
}

连接客户和组件
可以使用GUIDGEN.exe生成一个GUID

//
// GUIDs.cpp - 接口 ID
//
#include <objbase.h>

extern "C" 
{
    // {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IX = 
        {0x32bb8320, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IY = 
        {0x32bb8321, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IZ = 
        {0x32bb8322, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // The extern is required to allocate memory for C++ constants.
}

客户

//
// Client1.cpp
// 编译时, 使用: cl Client1.cpp Create.cpp GUIDs.cpp UUID.lib

#include <iostream.h>
#include <objbase.h>

#include "Iface.h"
#include "Create.h"

void trace(const char* msg) { cout << "Client 1:\t" << msg << endl ;}

//
// Client1
//
int main()
{
    HRESULT hr ;

    // Get the name of the component to use.
    char name[40] ;
    cout << "Enter the filename of a component to use [Cmpnt?.dll]: " ;
    cin  >> name ;
    cout << endl ;

    // 客户首先要求用户输出DLL名称
    // 然后调用指定DLL中输出的CreateInstance函数创建相应的组件
    trace("Get an IUnknown pointer.") ;
    IUnknown* pIUnknown = CallCreateInstance(name) ; 
    if (pIUnknown == NULL)
    {
        trace("CallCreateInstance Failed.") ;
        return 1 ;
    }

    trace("Get interface IX.") ;

    //查询接口
    IX* pIX ; 
    hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX) ;

    if (SUCCEEDED(hr))
    {
        trace("Succeeded getting IX.") ;
        pIX->Fx() ;          // 使用接口 IX.
        pIX->Release() ;     // 引用计数减1
    }
    else
    {
        trace("Could not get interface IX.") ;
    }

    trace("Release IUnknown interface.") ;
    pIUnknown->Release() ;   // 引用计数减1

    return 0 ;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值