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

COM本质论学习笔记(一)IDL
2008年09月16日 星期二 17:30

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,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,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);}

相关文章

Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强...
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办...
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace...
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用...
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选...
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As Dat...