• 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/

  • 相关阅读:
    python3 之 内置函数range() Be
    从零开始学习Sencha Touch MVC应用之十四
    从零开始学习Sencha Touch MVC应用之十六
    从零开始学习Sencha Touch MVC应用之十五
    从零开始学习Sencha Touch MVC应用之十三
    从零开始学习Sencha Touch MVC应用之十七
    从零开始学习Sencha Touch MVC应用之十七
    从零开始学习Sencha Touch MVC应用之十四
    从零开始学习Sencha Touch MVC应用之十三
    从零开始学习Sencha Touch MVC应用之十五
  • 原文地址:https://www.cnblogs.com/kind064100611/p/4420424.html
Copyright © 2020-2023  润新知