一、定义 library(类型库)
下面的表达式描述一个类型库．这个描述包括一个MIDL输入文件(ODL)包含的所有信息．

[attributes]
library 类型库的名字 {
输入库，数据类型，模块，接口，调度接口和COM类等相关的要暴露的信息的描述．
};
1.1、语法元素说明：
[ attributes ]
在一个library表达式前面接受helpstring,helpcontext,lcid,restricted,hidden,control,uuid和version属性．
其中uuid属性是必须的．想了解这些属性的详细信息，可参考下一章．
属性放在中括号中.
1.2、备注
library表达式必须出现在任何类型定义之前
1.3、例子
[
uuid(F37C8060-4AD5-101B-B826-00DD01103DE1), // LIBID_Hello.
helpstring("Hello 2.0 Type Library"),
lcid(0x0409),
version(2.0)
]
library Hello {
importlib("stdole.tlb");
[
uuid(F37C8062-4AD5-101B-B826-00DD01103DE1), // IID_Ihello.
helpstring("Application object for the Hello application."),
oleautomation,
dual
]
interface IHello : IDispatch {
[propget, helpstring("Returns the application of the object.")]
HRESULT Application([in, lcid] long localeID, [out, retval] IHello** retval)
}
}

二、定义接口(interface)
这个表达式定义一个接口，接口就是一个函数定义的集合．一个接口可以继承于任何基接口．

[attributes]
interface 接口的名字[:父接口的名字]{
functionlist
};
2.1、语法元素说明：
[attributes]
在一个interface表达式前面接受dual , helpstring , helpcontext , hidden , odl , oleautomation , uuid 和 version 属性．
其中 odl , uuid 属性是必须的．如果这个接口是一个COM对象的接口，source , default 和 restricted 也被接受．想了解这些属性的详细信息，可参考下一章．
functionlist
接口中每个函数的函数原形的列表．在这个函数列表中可以出现任意数量的函数定义．
在函数列表中的函数定义使用下面的形式：
[attributes] returntype [calling convention] funcname(params);
接口里一个函数定义中可以接受下面的属性：helpstring , helpcontext , string , propget , propput , propputref , bindable , defaultbind , displaybind 和 vararg ．如果 vararg 被指定，最后一个参数必须是VARIANT类型的安全数组．可选的调用惯例可以是 _pascal / _pascal / pascal , _cdecl / _cdecl / cdecl 或者 __stdcall / _stdcall / stdcall．调用协定
参数列表是一个用逗号分隔的列表，向下面这样：
[attributes] type paramname
类型可以是任何先前已经定义的类型，内置类型，指向任何类型的指针，指向内置类型的指针等．参数的属性有 in , out , optional 和 string．
如果使用了 optional ，它必须指定最右边的参数，而且参数的类型必须是VARIANT．
2.2、备注
因为用interface描述的函数存在于VTBL，DispInvoke 与 CreateStdDispatch 可以用于提供一个IDispatch::Invoke的实现．因为这个原因，在描述一个对象的属性或方法时interface 的使用比 dispinterface 更普遍．
在interface里描述一个函数，与在一个module表达式里描述是基本致的，除了entry属性不允许使用．
接口里的成员可能会产生异常，所以应该返回HRESULT值，而且应该为真实返回值指定一个返回参数．返回参数总是列表中最后一个参数．
2.3、例子
下面的例子定义了一个名字为Hello的接口，有两个成员函数，HelloProc和Shutdown:
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0)]
interface hello : IUnknown {
void HelloProc([in, string] unsigned char * pszString);
void Shutdown(void);
};
接下来的例子定义了一个名为IMyInt的双重接口，它有一对为MyMessage属性定义的访问函数，还有一个返回一个字符串的函数．
[dual]
interface IMyInt : IDispatch {
// A property that is a string.
[propget] HRESULT MyMessage([in, lcid] LCID lcid, [out, retval] BSTR *pbstrRetVal);
[propput] HRESULT MyMessage([in] BSTR rhs, [in, lcid] DWORD lcid);
// A method returning a string.
HRESULT SayMessage([in] long NumTimes, [in, lcid] DWORD lcid, [out, retval] BSTR *pbstrRetVal);
}
这个接口的成员返回错误信息，而且函数通过HRESULT值与返回参数各自地返回值．
访问成员的工具可以返回HRESULT到他们的用户，可简单的暴露返回参数返回值，显式地处理HRESULT值．
双重接口必须从IDispatch继承
三、定义coclass
这个表达式描述一个组件对象模型(COM)的全球统一标识符和它支持的接口．
[attributes]
coclass classname {
[attributes2] [interface | dispinterface] interfacename;
};

3.1、语法元素说明：
[attributes]
在coclass表达式中，uuid属性是必须的．这个uuid与在系统注册表中注册组件的CLSID是相同的．
在本表达式的前面还接受 helpstring , helpcontext , version , licensed , control , hidden 与 appobject 属性，但不是必须的．想了解这些属性更多的细节，请看下一章．appobject 属性使 coclass 的函数和属性在整个类型库内有效．
classname
在类型库中标识普通对象的名字．
attributes2
interface或dispinterface的可选属性．source , default 与 restricted 属性可以被接受．
interfacename
用 interface 或 dispinterface 声明的接口．
3.2、备注
组件对象模型定义一个类作为一个实现，允许QueryInterface在接口集之间查询．

3.3、示例

[ uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0), helpstring("A class"), helpcontext(2481), appobject]
coclass myapp {
[source] interface IMydocfuncs;
dispinterface DMydocfuncs;
};
[uuid 00000000-0000-0000-0000-123456789019]
coclass foo{
[restricted] interface bar;
interface bar;
}