21xrx.com
2024-11-08 21:14:59 Friday
登录
文章检索 我的文章 写文章
C++编写COM组件
2023-06-27 04:10:18 深夜i     --     --
C++ COM组件 编写 组件开发 面向对象编程

COM(Component Object Model)是Windows平台上的一种二进制接口技术,它允许不同进程之间的组件相互通信。COM组件是可以被C++编写的,这篇文章将介绍如何使用C++编写COM组件。

1. 编写COM组件的基本步骤

编写COM组件的基本步骤如下:

1)定义COM组件的接口;

2)实现COM组件的接口;

3)在COM组件内部实现对象的生命周期管理。

2. 定义COM组件的接口

我们可以使用IDL语言(Interface Definition Language)来定义COM组件的接口。IDL语言可以用于定义接口、结构体、枚举等数据类型。以下是一份简单的IDL文件的示例,其中定义了一个名为ISimpleCOM的接口:

IDL

import "unknwn.idl";

[

  uuid(12345678-1234-1234-1234-1234567890AB),

  version(1.0)

]

interface ISimpleCOM : IUnknown

{

  HRESULT SayHello();

};

3. 实现COM组件的接口

接下来,我们需要用C++代码实现ISimpleCOM接口。在C++中,我们可以使用MFC框架、ATL框架或者纯C++方式编写COM组件。下面的代码是使用纯C++方式实现ISimpleCOM接口的示例:


#include "stdafx.h"

#include <windows.h>

class CSimpleCOM : public ISimpleCOM

{

public:

  CSimpleCOM();

  virtual ~CSimpleCOM();

  // IUnknown interface

  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);

  virtual ULONG STDMETHODCALLTYPE AddRef();

  virtual ULONG STDMETHODCALLTYPE Release();

  // ISimpleCOM interface

  virtual HRESULT STDMETHODCALLTYPE SayHello();

private:

  ULONG m_nRef;

};

CSimpleCOM::CSimpleCOM()

: m_nRef(1)

{

}

CSimpleCOM::~CSimpleCOM()

{

}

HRESULT STDMETHODCALLTYPE CSimpleCOM::QueryInterface(REFIID riid, void **ppv)

{

  if (!ppv)

  {

    return E_INVALIDARG;

  }

  *ppv = NULL;

  if (IsEqualIID(riid, IID_IUnknown))

  {

    *ppv = static_cast<IUnknown *>(this);

  }

  else if (IsEqualIID(riid, IID_ISimpleCOM))

  {

    *ppv = static_cast<ISimpleCOM *>(this);

  }

  else

  {

    return E_NOINTERFACE;

  }

  static_cast<IUnknown *>(*ppv)->AddRef();

  return S_OK;

}

ULONG STDMETHODCALLTYPE CSimpleCOM::AddRef()

{

  return InterlockedIncrement(&m_nRef);

}

ULONG STDMETHODCALLTYPE CSimpleCOM::Release()

{

  ULONG nCount = InterlockedDecrement(&m_nRef);

  if (nCount == 0)

  {

    delete this;

  }

  return nCount;

}

HRESULT STDMETHODCALLTYPE CSimpleCOM::SayHello()

{

  MessageBox(NULL, TEXT("Hello, World!"), TEXT("SimpleCOM"), MB_OK);

  return S_OK;

}

在上述示例代码中,CSimpleCOM类实现了ISimpleCOM接口中定义的所有方法。QueryInterface方法用于查询COM组件暴露的接口,AddRef和Release方法用于控制对象的引用计数,SayHello方法用于弹出消息框并显示“Hello, World!”信息。

4. 管理对象的生命周期

在COM组件内部,我们还需要实现对象的生命周期管理。COM组件需要负责自己的创建、销毁和垃圾回收。以下是一些常见的生命周期管理的方法:

1)使用CreateObject / CoCreateInstance函数创建COM组件实例;

2)在COM组件的析构函数中释放所有资源;

3)在COM组件的AddRef / Release方法中维护对象的引用计数。

对于对象的创建和销毁,我们可以使用标准的C++ new / delete运算符,也可以使用COM规定的CoTaskMemAlloc / CoTaskMemFree函数。以下是一个示例代码,通过标准C++运算符实现了对象的创建和销毁:


HRESULT STDMETHODCALLTYPE CreateSimpleCOM(ISimpleCOM **ppSimpleCOM)

{

  if (!ppSimpleCOM)

  {

    return E_INVALIDARG;

  }

  *ppSimpleCOM = new CSimpleCOM();

  if (*ppSimpleCOM == NULL)

  {

    return E_OUTOFMEMORY;

  }

  (*ppSimpleCOM)->AddRef();

  return S_OK;

}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)

{

  if (!ppv)

  {

    return E_INVALIDARG;

  }

  *ppv = NULL;

  if (!IsEqualGUID(rclsid, CLSID_SimpleCOM))

  {

    return CLASS_E_CLASSNOTAVAILABLE;

  }

  CClassFactory *pClassFactory = new CClassFactory();

  if (pClassFactory == NULL)

  {

    return E_OUTOFMEMORY;

  }

  HRESULT hr = pClassFactory->QueryInterface(riid, ppv);

  pClassFactory->Release();

  return hr;

}

5. 注册和使用COM组件

在实现好COM组件之后,我们需要将它注册到Windows系统中以便其他进程可以使用它。Windows提供了注册表用于保存COM组件的信息,我们需要将COM组件的信息写入注册表中。

要注册COM组件,我们可以手动编写注册表文件,也可以使用REGSVR32工具来注册COM组件。以下是手动编写注册表文件的示例,其中,HKEY_CLASSES_ROOT\CLSID\{CLSID of SimpleCOM}键包含COM组件的全局唯一标识符(GUID),HKEY_CLASSES_ROOT\CLSID\{CLSID of SimpleCOM}\InprocServer32键指定了COM组件的DLL文件路径:

registry

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{12345678-1234-1234-1234-1234567890AB}]

@="SimpleCOM Class"

[HKEY_CLASSES_ROOT\CLSID\{12345678-1234-1234-1234-1234567890AB}\InProcServer32]

@="C:\\Windows\\System32\\SimpleCOM.dll"

"ThreadingModel"="Apartment"

在注册COM组件之后,在其他进程中使用COM组件也很简单。首先,我们需要使用CoInitialize / CoInitializeEx函数初始化COM运行时。然后,使用CoCreateInstance函数创建COM组件的实例,调用COM组件的方法,最后使用CoUninitialize函数释放COM运行时。以下是一个使用COM组件的示例程序:


#include "stdafx.h"

#include <windows.h>

#include <objbase.h>

int main(int argc, char* argv[])

{

  CoInitialize(NULL);

  ISimpleCOM *pSimpleCOM = NULL;

  HRESULT hr = CoCreateInstance(CLSID_SimpleCOM, NULL, CLSCTX_INPROC_SERVER, IID_ISimpleCOM, (void **)&pSimpleCOM);

  if (hr != S_OK)

  {

    return -1;

  }

  pSimpleCOM->SayHello();

  pSimpleCOM->Release();

  CoUninitialize();

  return 0;

}

综上所述,C++编写COM组件需要定义COM组件的接口,实现接口,管理对象的生命周期,并将COM组件注册到Windows系统中。在使用COM组件时,需要使用CoInitialize / CoInitializeEx函数初始化COM运行时,使用CoCreateInstance函数创建COM组件实例,使用COM组件的方法,最后使用CoUninitialize函数释放COM运行时。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复