將編寫好的ODL文件往MKTYPLIB.EXE上一拖即可。它是個(gè) tlb庫(kù)文件文件生成工具,從VC中提取了出來(lái),使用時(shí)解壓就可以用了,然后直接把 odl 文件拖到mktyplib.exe上即可生成 tlb 文件了。
定義 library(類型庫(kù))
下面的表達(dá)式描述一個(gè)類型庫(kù).這個(gè)描述包括一個(gè)MIDL輸入文件(ODL)包含的所有信息.
[attributes]
library 類型庫(kù)的名字 {
輸入庫(kù),數(shù)據(jù)類型,模塊,接口,調(diào)度接口和COM類等相關(guān)的要暴露的信息的描述.
};
1.1、語(yǔ)法元素說(shuō)明:
[ attributes ]
在一個(gè)library表達(dá)式前面接受helpstring,helpcontext,lcid,restricted,hidden,control,uuid和version屬性.
其中uuid屬性是必須的.想了解這些屬性的詳細(xì)信息,可參考下一章.
屬性放在中括號(hào)中.
1.2、備注
library表達(dá)式必須出現(xiàn)在任何類型定義之前
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)
這個(gè)表達(dá)式定義一個(gè)接口,接口就是一個(gè)函數(shù)定義的集合.一個(gè)接口可以繼承于任何基接口.
[attributes]
interface 接口的名字[:父接口的名字]{
functionlist
};
2.1、語(yǔ)法元素說(shuō)明:
[attributes]
在一個(gè)interface表達(dá)式前面接受dual , helpstring , helpcontext , hidden , odl , oleautomation , uuid 和 version 屬性.
其中 odl , uuid 屬性是必須的.如果這個(gè)接口是一個(gè)COM對(duì)象的接口,source , default 和 restricted 也被接受.想了解這些屬性的詳細(xì)信息,可參考下一章.
functionlist
接口中每個(gè)函數(shù)的函數(shù)原形的列表.在這個(gè)函數(shù)列表中可以出現(xiàn)任意數(shù)量的函數(shù)定義.
在函數(shù)列表中的函數(shù)定義使用下面的形式:
[attributes] returntype [calling convention] funcname(params);
接口里一個(gè)函數(shù)定義中可以接受下面的屬性:helpstring , helpcontext , string , propget , propput , propputref , bindable , defaultbind , displaybind 和 vararg .如果 vararg 被指定,最后一個(gè)參數(shù)必須是VARIANT類型的安全數(shù)組.可選的調(diào)用慣例可以是 _pascal / _pascal / pascal , _cdecl / _cdecl / cdecl 或者 __stdcall / _stdcall / stdcall.調(diào)用協(xié)定
參數(shù)列表是一個(gè)用逗號(hào)分隔的列表,向下面這樣:
[attributes] type paramname
類型可以是任何先前已經(jīng)定義的類型,內(nèi)置類型,指向任何類型的指針,指向內(nèi)置類型的指針等.參數(shù)的屬性有 in , out , optional 和 string.
如果使用了 optional ,它必須指定最右邊的參數(shù),而且參數(shù)的類型必須是VARIANT.
2.2、備注
因?yàn)橛胕nterface描述的函數(shù)存在于VTBL,DispInvoke 與 CreateStdDispatch 可以用于提供一個(gè)IDispatch::Invoke的實(shí)現(xiàn).因?yàn)檫@個(gè)原因,在描述一個(gè)對(duì)象的屬性或方法時(shí)interface 的使用比 dispinterface 更普遍.
在interface里描述一個(gè)函數(shù),與在一個(gè)module表達(dá)式里描述是基本致的,除了entry屬性不允許使用.
接口里的成員可能會(huì)產(chǎn)生異常,所以應(yīng)該返回HRESULT值,而且應(yīng)該為真實(shí)返回值指定一個(gè)返回參數(shù).返回參數(shù)總是列表中最后一個(gè)參數(shù).
2.3、例子
下面的例子定義了一個(gè)名字為Hello的接口,有兩個(gè)成員函數(shù),HelloProc和Shutdown:
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0)]
interface hello : IUnknown {
void HelloProc([in, string] unsigned char * pszString);
void Shutdown(void);
};
接下來(lái)的例子定義了一個(gè)名為IMyInt的雙重接口,它有一對(duì)為MyMessage屬性定義的訪問(wèn)函數(shù),還有一個(gè)返回一個(gè)字符串的函數(shù).
[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);
}
這個(gè)接口的成員返回錯(cuò)誤信息,而且函數(shù)通過(guò)HRESULT值與返回參數(shù)各自地返回值.
訪問(wèn)成員的工具可以返回HRESULT到他們的用戶,可簡(jiǎn)單的暴露返回參數(shù)返回值,顯式地處理HRESULT值.
雙重接口必須從IDispatch繼承
定義coclass
這個(gè)表達(dá)式描述一個(gè)組件對(duì)象模型(COM)的全球統(tǒng)一標(biāo)識(shí)符和它支持的接口.
[attributes]
coclass classname {
[attributes2] [interface | dispinterface] interfacename;
};
3.1、語(yǔ)法元素說(shuō)明:
[attributes]
在coclass表達(dá)式中,uuid屬性是必須的.這個(gè)uuid與在系統(tǒng)注冊(cè)表中注冊(cè)組件的CLSID是相同的.
在本表達(dá)式的前面還接受 helpstring , helpcontext , version , licensed , control , hidden 與 appobject 屬性,但不是必須的.想了解這些屬性更多的細(xì)節(jié),請(qǐng)看下一章.a(chǎn)ppobject 屬性使 coclass 的函數(shù)和屬性在整個(gè)類型庫(kù)內(nèi)有效.
classname
在類型庫(kù)中標(biāo)識(shí)普通對(duì)象的名字.
attributes2
interface或dispinterface的可選屬性.source , default 與 restricted 屬性可以被接受.
interfacename
用 interface 或 dispinterface 聲明的接口.
3.2、備注
組件對(duì)象模型定義一個(gè)類作為一個(gè)實(shí)現(xiàn),允許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;
}