• COM本质论学习笔记(一)IDL


    IDL是Interface Definition Language的所写,翻译为接口定义语言

    1.该语言规定,必须显式的为每个接口函数指定参数的目的,例如
    HRESULT foo([in]long* Input, [out]long* Output, [in, out]long* InAndOut);

    2.通常,函数的返回值为HRESULT,表示执行的状况,以便被其他语言所捕获,例如Visual Basic等。HRESULT大体分为三个部分:

    31|30 29|28 ... 16|15 ...0
    成 | 保留 |   操作码 | 信息码





    第31位如果是0那么代表成功,否则代表失败,这也是Win32 SDK的SUCCESSED宏判断的依据:
    #define SUCCESSED(hr) (long(hr) >= 0)
    #define FAILD(hr) (long(hr) < 0)

    3.该返回值只提供了函数的执行情况,函数可以另外提供返回值:
    HRESULT foo([in]long* Input, [out]long* Output, [out, retval]long* InAndOut);
    该函数在VB里看起来应该是这样的(凭记忆,未验证):
    Public Declare Function foo(ByVal Input as Integer, ByRef Output as Integer) as Integer
    如果在VB中调用该函数失败了,那么不是通过返回值把错误码返回,而是VB的解释器触发一个异常,你需要在VB里用On Error xxxx来进行错误处理。

    4.声明一个接口。接口的声明是如下形式滴~
    [object, uuid(00000000-0000-0000-0000-000000000000)]
    interface IMyInterface : IBaseInterface
    {
        enum MyEnum
        {
            ME_aa,
            ME_bb,
        }
        typedef struct _ASTRUCT
        {
            MyEnum me;
            long val;
        }
        HRESULT foo1([in]LONG* Input, [out, retval]RetVal);
    }

    []中的部分是接口属性,其中object代表这是一个com接口,后面的部分是全局唯一标识符(GUID),当用在com接口时,也叫做接口标识符(IID)。

    接下来IMyInterface是接口名,IBaseInterface是基接口名
    {}中则是接口体。

    5.细说GUID\IID\CLSID
    GUID是个128位的大数,所以COM用一个结构体来表示GUID
    typedef struct _GUID
    {
        DWORD  Data1;
        WORD    Data2;
        WORD    Data3;
        BYTE      Data4[8];
    }GUID;
    你看 (4+2+2+8)*8=128.
    同时,还有如下定义:
    typedef GUID IID;
    typedef GUID CLSID;

    所以说,IID,CLSID和GUID都是一种东东。
    有时为了判断2个GUID是否相等,那么用引用就会很高效,所以还有如下宏定义,以及== 和 !=操作符:
    #define REFGUID   const GUID&
    #define REFIID      const IID&
    #define REFCLSID  const CLSID&

    这个GUID/IID通常用VCSDK附带的GUIDGEN.EXE来生成,理论上不会重复~

    6.结构体与联合体
    在IDL中也可以声明结构体和联合体
    typedef struct _TestStruct
    {
        long a;
        short b;
    }TESTSTRUCT;

    struct TESTSTRUCT2
    {
        long a;
        short b;
    };

    union VALUE
    {
        [case(1)]long a;
        [case(2)]short b;
    };

    也可以在结构体或者函数中使用联合:
    struct TESTSTRUCT3
    {
        short t;
        [switch_is(t)]union VALUE
        {
            [case(1)]long a;
            [case(2)]short b;
        };
    };

    HRESULT foo1([in, switch_is(t)]union VALUE* pu, [in]short t);

    7.属性
    给接口添加属性,可以使用户感觉更良好:
    [object, uuid(...)]
    interface IPropertyInterface : IUnknown
    {
        // 只读
        [propget] HRESULT Age([out, retval]long* RetVal);

        // 读写
        [propput] HRESULT ID([in]long id);
        [propget] HRESULT ID([out, retval]long* id);
    }
    实现这样的接口也比较容易,只需要在C++类对应的方法前加get_或者put_即可
    class CPropertyInterface : public IPropertyInterface
    {
        public:
        ....
        HRESULT get_Age(long* RetVal);
        HRESULT get_ID(long* RetVal);
        HRESULT put_ID(long id);
    }

  • 相关阅读:
    AJAX省市县三级联动
    AJAX,JSON搜索智能提示
    AJAX,JSON用户名校验
    原生JS操作AJAX
    JSON和GSON操作json数据
    Servlet之Cookie操作
    路径问题--转发、重定向、表单、超链接
    4418: [Shoi2013]扇形面积并|二分答案|树状数组
    近200篇机器学习&amp;深度学习资料分享
    【Android】Eclipse自己主动编译NDK/JNI的三种方法
  • 原文地址:https://www.cnblogs.com/yoran/p/1099601.html
Copyright © 2020-2023  润新知