010-COM开发入门基础及实例

COM开发入门基础及实例

组件对象模型(Component Object Model,简称COM)是Microsoft开发的一种二进制接口标准,用于实现软件组件间的互操作。COM是Windows平台上许多关键技术的基础,包括ActiveX、OLE、DirectX和Windows Shell等。本文将介绍COM的基本概念、工作原理,并通过实例演示如何开发COM组件。

1. COM基础概念

1.1 COM的核心特性

COM基于以下几个核心概念:

  • 接口:所有COM组件通过接口与外界交互,接口是一组相关函数的集合
  • 引用计数:管理组件生命周期的机制
  • 接口查询:允许客户端发现组件支持的功能
  • 二进制兼容性:组件可以在不同版本间保持兼容
  • 语言独立性:COM组件可以用任何语言编写,并被任何语言调用

1.2 IUnknown接口

所有COM接口都继承自IUnknown,它定义了三个基本方法:

cpp

interface IUnknown {
    HRESULT QueryInterface(REFIID riid, void** ppvObject);
    ULONG AddRef();
    ULONG Release();
};
  • QueryInterface:允许客户端查询组件支持的其他接口
  • AddRef:增加引用计数
  • Release:减少引用计数,当计数为零时释放组件

1.3 GUID和接口标识符

COM使用全局唯一标识符(GUID)来标识每个接口和组件:

cpp

// IExample接口的ID定义
// {12345678-1234-1234-1234-123456789ABC}
DEFINE_GUID(IID_IExample, 
0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc);

2. 创建第一个COM组件

2.1 定义接口

首先定义一个自定义接口:

cpp

// ICalculator.h
#include <unknwn.h>

// {5B4F9CEF-3742-4B9B-8F26-B8C0B2D238A6}
DEFINE_GUID(IID_ICalculator, 
0x5b4f9cef, 0x3742, 0x4b9b, 0x8f, 0x26, 0xb8, 0xc0, 0xb2, 0xd2, 0x38, 0xa6);

// 定义计算器接口
interface ICalculator : public IUnknown {
    virtual HRESULT __stdcall Add(int a, int b, int* result) = 0;
    virtual HRESULT __stdcall Subtract(int a, int b, int* result) = 0;
    virtual HRESULT __stdcall Multiply(int a, int b, int* result) = 0;
    virtual HRESULT __stdcall Divide(int a, int b, int* result) = 0;
};

2.2 实现组件类

接下来实现组件类:

cpp

// Calculator.h
#include "ICalculator.h"
#include <atomic>

// {8C42B6C0-9C8A-4C54-B2A5-E9D9D4E4D178}
DEFINE_GUID(CLSID_Calculator, 
0x8c42b6c0, 0x9c8a, 0x4c54, 0xb2, 0xa5, 0xe9, 0xd9, 0xd4, 0xe4, 0xd1, 0x78);

class Calculator : public ICalculator {
public:
    // IUnknown方法
    HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override;
    ULONG __stdcall AddRef() override;
    ULONG __stdcall Release() override;
    
    // ICalculator方法
    HRESULT __stdcall Add(int a, int b, int* result) override;
    HRESULT __stdcall Subtract(int a, int b, int* result) override;
    HRESULT __stdcall Multiply(int a, int b, int* result) override;
    HRESULT __stdcall Divide(int a, int b, int* result) override;
    
    // 构造和析构函数
    Calculator();
    ~Calculator();

private:
    std::atomic<ULONG> m_refCount;
};

2.3 实现组件方法

cpp

// Calculator.cpp
#include "Calculator.h"

// 构造函数
Calculator::Calculator() : m_refCount(1) {
    // 初始化工作
}

// 析构函数
Calculator::~Calculator() {
    // 清理工作
}

// IUnknown方法实现
HRESULT __stdcall Calculator::QueryInterface(REFIID riid, void** ppvObject) {
    if (ppvObject == NULL) {
        return E_POINTER;
    }
    
    if (riid == IID_IUnknown) {
        *ppvObject = static_cast<IUnknown*>(this);
    }
    else if (riid == IID_ICalculator) {
        *ppvObject = static_cast<ICalculator*>(this);
    }
    else {
        *ppvObject = NULL;
        return E_NOINTERFACE;
    }
    
    AddRef();
    return S_OK;
}

ULONG __stdcall Calculator::AddRef() {
    return ++m_refCount;
}

ULONG __stdcall Calculator::Release() {
    ULONG newCount = --m_refCount;
    
    if (newCount == 0) {
        delete this;
    }
    
    return newCount;
}

// ICalculator方法实现
HRESULT __stdcall Calculator::Add(int a, int b, int* result) {
    if (result == NULL) {
        return E_POINTER;
    }
    
    *result = a + b;
    return S_OK;
}

HRESULT __stdcall Calculator::Subtract(int a, int b, int* result) {
    if (result == NULL) {
        return E_POINTER;
    }
    
    *result = a - b;
    return S_OK;
}

HRESULT __stdcall Calculator::Multiply(int a, int b, int* result) {
    if (result == NULL) {
        return E_POINTER;
    }
    
    *result = a * b;
    return S_OK;
}

HRESULT __stdcall Calculator::Divide(int a, int b, int* result) {
    if (result == NULL) {
        return E_POINTER;
    }
    
    if (b == 0) {
        return E_INVALIDARG;  // 除数不能为零
    }
    
    *result = a / b;
    return S_OK;
}

2.4 实现类工厂

类工厂负责创建组件实例:

cpp

// CalculatorFactory.h
#include <unknwn.h>

class CalculatorFactory : public IClassFactory {
public:
    // IUnknown方法
    HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override;
    ULONG __stdcall AddRef() override;
    ULONG __stdcall Release() override;
    
    // IClassFactory方法
    HRESULT __stdcall CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝哥Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值