COM---动态链接

来源:互联网 发布:php单引号转义函数 编辑:程序博客网 时间:2024/06/05 18:49

定义接口

//// 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 ;}//引用计数加1ULONG __stdcall CA::AddRef(){    return InterlockedIncrement(&m_cRef) ;}//引用计数减1ULONG __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.dllDESCRIPTION     '(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 0
原创粉丝点击