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