COM使用简介

1. 全球唯一标识符GUID是用来在注册表中确定COM的dll位置的。
接口ID(IID)用来查找同一个COM中的不同接口的。
GUID不用记,可以用hResult = ::CLSIDFromProgID(L"COMtest.Object", &firstComCLSID);去注册表查找,COMtest.Object为建COM时标记的,用来找GUID。
hResult = CoCreateInstance(firstComCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnknown);
它会返回一个IUnknown指针,指向这个COM的第一个接口上,以后可以用
hResult = pUnknown->QueryInterface(IID_IFirstCOM, (void **)&pFirstCom);查找接口。
(经常有些偷懒的人在CoCreateInstance中直接用接口的指针拿来搞,我感觉就问题哈,多个接口怎么办,不断构造COM么。。。)

2. 头文件,应该为这2个

#include "..COMtestCOMtestCOMtest_i.h"
#include "..COMtestCOMtestCOMtest_i.c"
就不需要自己输入
const IID IID_IFirst_ATL = {
0xD5870BE7,0x26BD,0x4FCD,
{0x8C,0x54,0xF8,0x9C,0xE1,0xEC,0xCF,0x6F}
};
const CLSID CLSID_First_ATL = {
0x2BA452EE,0x1D19,0x4E10,
{0xAA,0xD4,0x6D,0x1A,0x8E,0xD2,0x44,0x2E}
};这些东西了。


3. vs2008的ATL简单对象一个COM只有一个接口,插入多个ATL简单对象是没用的,那是多个COM,(一个dll可以有多个COM),还会造成CoCreateInstance失败,这不是多接口(浪费我好多时间)。多接口需要手动插入,http://www.vckbase.com/document/viewdoc/?id=1501 。


4. 杨老师使用的是自定义(custom)的接口,我用了dual 双接口,删掉嫌麻烦,修改就不大一样
public IDispatchImpl<ISecondCOM, &IID_ISecondCOM, &LIBID_COMtestLib, /*wMajor =*/ 1, /*wMinor =*/ 0> 还有其他。。。
而且编译错误

BEGIN_COM_MAP(CFirstCOM)
//COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IFirstCOM)
COM_INTERFACE_ENTRY(ISecondCOM)
END_COM_MAP()
把COM_INTERFACE_ENTRY(IDispatch)测试通过了。

附上我的测试代码:

#include "..COMtestCOMtestCOMtest_i.h"
#include "..COMtestCOMtestCOMtest_i.c"
#include <stdio.h>

void main()
{
    HRESULT hResult = 0;
    IUnknown *pUnknown;//组件的实例只有一个IUnknown接口
    IFirstCOM* pFirstCom;//接口指针
    if (!SUCCEEDED(CoInitialize(NULL))) //初始化COM库
    {
        printf("Initialize COM library failed!
");
        return ;
    }

    GUID firstComCLSID;
    hResult = ::CLSIDFromProgID(L"COMtest.Object", &firstComCLSID);
    if (!SUCCEEDED(hResult)) 
    {
        printf("Can't find the TestCom CLSID!
");
        return;
    }
    /*通过组件标识ID创建一个组件实例,pUnknown返回组件的一个通用接口,
    通过它可以查询我们想要的接口, CLSTX_INPROC_SERVER表示是进程类主键,
    其实此处也通过InProcServer32查找到组件的路径并加载到内存*/
    hResult = CoCreateInstance(firstComCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnknown);
    if (!SUCCEEDED(hResult)) 
    {
        printf("Create object failed!
");
        return;
    }
    /*查找要使用的接口,IDD_TestCom是组件的标识符,通过该标识符也就查找到对应的接口了
    该标识符由服务端组件告知,否则写的组件也就失去其意义。*/
    hResult = pUnknown->QueryInterface(IID_IFirstCOM, (void **)&pFirstCom);

    if (!SUCCEEDED(hResult)) 
    {
        pUnknown->Release();
        printf("QueryInterface first ITestInterFace failed!
");
        return;
    }
    //查找到接口后调用接口提供的功能
    long ReturnValue; 
    pFirstCom->Add(5,7,&ReturnValue);
    printf("The answer for 5 + 7 is: %ld
",ReturnValue);

    ISecondCOM* pSecondCom;//接口指针
    hResult = pUnknown->QueryInterface(IID_ISecondCOM, (void **)&pSecondCom);
    pSecondCom->Sub(5,7,&ReturnValue);
    printf("The answer for 5 - 7 is: %ld
",ReturnValue);
    pSecondCom->Release();

    //告诉接口,不在使用
    pFirstCom->Release();


    //判断该接口是否还被使用
    if (pUnknown->Release() == 0)
    {
        printf("Com Free Succeeded!
");
    }

    CoUninitialize();//清理环境
}

Reference: http://www.vckbase.com/vckbase/columnist/yangfeng/

原文地址:https://www.cnblogs.com/kind064100611/p/4420424.html