IDL詳解,什么是IDL和MIDL?
Question:
什么是IDL和MIDL?
?
Answer:
IDL是接口定義語言。
MIDL是Microsoft的IDL編譯器。
?
在用IDL對(duì)接口和組件進(jìn)行了描述后,可以用MIDL進(jìn)行編譯,生成相應(yīng)的代理和存根DLL的C代碼。
?
一個(gè)例子:
import “unknown.idl” ///用于將其他IDL文件中的定義包含到當(dāng)前文件中
///Interface IX
[ ///注意是[ ]不是 {}
object, ///所定義的接口是一個(gè)COM接口
uuid(32bb8323-b41b-11cf-a6bb-0080c7b2d682), ///相應(yīng)的接口IID
helpstring(“IX Interface”), ///將幫助串放入類型庫
pointer_default(unique) ///這類指針可以為空,函數(shù)內(nèi)可以修改它們的值,但不能指定別名
]
interface IX:IUnknown
{
///in關(guān)鍵字告訴MIDL需要將此參數(shù)值從客戶傳遞給組件,存根代碼不需要送回任何值。
HRESULT FxStringIn([in,string]wchar_t* szIn);
///out關(guān)鍵字告訴MIDL參數(shù)僅被用來從組件向客戶傳回有關(guān)的數(shù)據(jù),
///代理不需要對(duì)輸出參數(shù)進(jìn)行列集,也不需要將參數(shù)傳給組件。
HRESULT FxStringOut([out,string]wchar_t* szout);
///COM對(duì)字符串的標(biāo)準(zhǔn)約定是Unicode字符(即wchar_t)
}
IDL文件可以定義C和C++風(fēng)格的結(jié)構(gòu),并可用它們作為函數(shù)的參數(shù)。
當(dāng)IDL文件中有一個(gè)library時(shí),MIDL將生成一個(gè)類型庫。
MIDL為接口生成相應(yīng)的代理和存根的C代碼。
為得到一個(gè)代理/存根DLL,需要編譯和鏈接MIDL生成的C文件。
宏REGISTER_PROXY_DLL將完成代理/存根DLL在注冊(cè)表中的注冊(cè)操作。
?
有了IDL和MIDL我們就可以象調(diào)用進(jìn)程內(nèi)組件那樣進(jìn)行跨進(jìn)程邊界的函數(shù)調(diào)用,并對(duì)參數(shù)進(jìn)行列集(marshal)。
?
Question:
什么是代理和存根DLL?
?
Answer:
客戶與一個(gè)模仿組件的DLL進(jìn)行通信,這個(gè)DLL可以完成參數(shù)的列集,此組件被稱為代理。
一個(gè)代理就是同另一個(gè)組件行為相同的組件。
代理必須是DLL形式。
組件還需要一個(gè)存根的DLL,以便對(duì)從客戶傳來的數(shù)據(jù)進(jìn)行散集。
存根也將對(duì)傳回給客戶的數(shù)據(jù)進(jìn)行列集。
?
?
接口定義語言(IDL)簡介
1.ATL不為實(shí)現(xiàn)類創(chuàng)建虛函數(shù)表,因此初始化成員放在一個(gè)公共的函數(shù)中(啥意思?!).
2.IDL(接口定義語言)
3.IDL文件由MIDL編譯器編譯。
4.IDL基礎(chǔ):
接口定義語言是一種方法,通過這種方法,可以定義COM對(duì)象所支持的接口。一個(gè)COM對(duì)象的IDL文件主要包括兩個(gè)
主要的元素:接口聲明和類型庫聲明。
5.接口
接口是COM組件的一個(gè)關(guān)鍵部分,由關(guān)鍵字interface定義。接口的屬性包括:
object, uuid(), helpstring(), pointer_default()。
Istopwatch?:?public?IUnknown
{
...
}
以后無論那里使用uuidof(IStopwatch)即可,例如
hr?=?CoCreateInstance(_uuidof(TIMERSlib::Stopwatch,NULL,CLSCTX_INPROC_SERVER,_uuifof(IStopwatch),void**&pStopwatch));
將返回與接口相關(guān)聯(lián)的GUID。宏_declspec(novtable)是微軟專用的,用作防止創(chuàng)建虛函數(shù)表的優(yōu)化。
6.方法:
COM方法的一般形式為:[attributes]HRESULT?name(param_list)
7.參數(shù)
主要分析3個(gè)參數(shù)in,out,retval。這三個(gè)參數(shù)中in,out是最重要的,這些屬性表示了參數(shù)傳遞數(shù)據(jù)的方向。retval屬性是一種方便的將數(shù)據(jù)返回給客戶端程序的方法。
?
OMG 接口定義語言(IDL)
?
用 RPC / COM /CORBA 技術(shù)來編寫分布式系統(tǒng)時(shí)都需要接口定義語言 (IDL)。
IDL特點(diǎn):
1、IDL 是一種規(guī)范語言。
2、IDL 看上去很像 C 語言。
3、OMG IDL 的目的是定義接口和精簡分布對(duì)象的過程。
4、IDL分離對(duì)象的接口與其實(shí)現(xiàn)。
5、IDL剝離了編程語言和硬件的依賴性。
6、使用IDL定義接口的客戶機(jī)程序員不知道接口背后的實(shí)現(xiàn)細(xì)節(jié)。
7、IDL提供一套通用的數(shù)據(jù)類型,并以這些數(shù)據(jù)類型來定義更為復(fù)雜的數(shù)據(jù)類型。
?
本文講解 OMG IDL 的內(nèi)置類型和關(guān)鍵字。
OMG 接口定義語言內(nèi)置類型表:
類型?范圍?最小大?。╞it)?
short?-215 到 215-1?16?
unsigned short?0 到 216-1?16?
long?-231 到 231-1?32?
unsigned long?0 到 232-1?32?
long long?-263 到 263-1?64?
Unsigned long long?0 到 264-1?64?
float?IEEE 單精度?32?
double?IEEE 雙精度?64?
long double?IEEE 雙字節(jié)擴(kuò)展浮點(diǎn)數(shù)?15 位指數(shù),64 位帶符號(hào)小數(shù)?
char?ISO Latin-1?8?
wchar?從任何寬字符集編碼寬字符,如 Unicode?依賴于實(shí)現(xiàn)?
string?ISO Latin-1,除了 ASCII NUL 以外?可變化?
Boolean?TRUE 或 FALSE?未指定?
octet?0 到 255?8?
any?自己描述的數(shù)據(jù)類型,可表示任何 IDL 類型?可變化?
?
IDL 基本類型
整數(shù)類型
OMG IDL 摒棄int 類型在不同平臺(tái)上取值范圍不同帶來的多義性的問題。
IDL提供2 字節(jié) (short)、4 字節(jié) (long) 和 8 字節(jié) (long long) 的整數(shù)類型。
所有這些整數(shù)類型都有相應(yīng)的無符號(hào)數(shù)類型。
浮點(diǎn)類型
OMG IDL 浮點(diǎn)數(shù)類型 float、double 和 long double。
OMG IDL 遵循 IEEE 754-1985 二進(jìn)制浮點(diǎn)數(shù)算術(shù)的標(biāo)準(zhǔn)。
目前,long double 用于巨大數(shù)字,有些語言映射還不支持這種類型。
char 和 wchar
IDL標(biāo)準(zhǔn)字符集:詞法約定(表示 IDL 文件的關(guān)鍵字、注釋和文字的字符記號(hào))規(guī)定 ISO 8859.1 字符集表示 IDL 文件中的字符。ISO 464 定義了空字符(null)和其它圖形字符。
OMG IDL必須處理從一個(gè)計(jì)算機(jī)系統(tǒng)到另一個(gè)計(jì)算機(jī)系統(tǒng)之間的字符傳輸。從一個(gè)字符代碼集到另一個(gè)字符代碼集的轉(zhuǎn)換,取決于語言綁定。
OMG IDL char 是一個(gè) 8 位變量,可以用兩種方法表示一個(gè)字符。
首先,它可以從面向字節(jié)的代碼集編碼單字節(jié)字符。
其次,在數(shù)組中使用時(shí),可以從多字節(jié)字符集(如 Unicode),編碼任何多字節(jié)字符。OMG IDL Wchar 只允許大于 8 個(gè)字節(jié)的代碼集。規(guī)范不支持特殊的代碼集。
OMG IDL Wchar允許每個(gè)客戶機(jī)和服務(wù)器使用本機(jī)的代碼集,然后指定如何轉(zhuǎn)換字符和字符串,以便在使用不同代碼集的環(huán)境之間進(jìn)行傳輸。
Boolean
Boolean 值只能是 TRUE 或 FALSE。
Octet
octet 是 8 位類型,一種非常重要的類型。
octet 在地址空間之間傳送時(shí)不會(huì)有任何表示更改。octet 在發(fā)送二進(jìn)制數(shù)據(jù),并且將它打包時(shí),它的形式仍然相同。其它每種 IDL 類型在傳輸時(shí)都有表示變化。例如,根據(jù) IOR 代碼集信息的指示,char 數(shù)組會(huì)經(jīng)歷代碼集轉(zhuǎn)換。而 octet 數(shù)組卻不會(huì)。
any 類型
IDL any 是一種包含任何數(shù)據(jù)類型的結(jié)構(gòu)。
IDL any由類型碼和值組成。類型碼描述 any 的值的內(nèi)容。
IDL any該類型可以是 char 或 long long 或 string 或另一種 any,或者是已經(jīng)創(chuàng)建的一種類型,如 Address。
IDL any?類似于C++ 的自我描述數(shù)據(jù)類型void *,但它更安全。
IDL any?類似于 Visual Basic的用戶定義的類型variant。
?
OMG IDL提供自定義數(shù)據(jù)類型,可以是枚舉、結(jié)構(gòu)和聯(lián)合,或者用 typedef 創(chuàng)建的新類型。
命名的類型
應(yīng)該使用 typedef 創(chuàng)建新的類型名稱,這將幫助解釋接口或保存輸入。
例如, typedef float AtmosPressure;
在文體上,應(yīng)注意不要為現(xiàn)有類型創(chuàng)建別名。CORBA 規(guī)范不保證 short 的兩種 typedef 是兼容的和可互換的。
OMG IDL typedef 關(guān)鍵字具體含義取決于其所映射到的實(shí)現(xiàn)語言。在 C++ 中,typedef 關(guān)鍵字表示類型定義,實(shí)際上別名也許是更為精確的術(shù)語。
枚舉
OMG IDL 枚舉是將名稱附加到數(shù)字的一種方法,從而了解代碼更多的含義。
OMG IDL 版的枚舉看上去象 C++ 版本的枚舉。
例如, enum CloudCover{cloudy, sunny};
CloudCover 現(xiàn)在就成為可以在 IDL 中使用的一種新類型。
枚舉最多有 232 個(gè)標(biāo)識(shí)。
規(guī)范中沒有規(guī)定標(biāo)識(shí)的有序數(shù)值。
OMG IDL 不允許空的枚舉。
結(jié)構(gòu)
struct 關(guān)鍵字提供了將一組變量集中到一個(gè)結(jié)構(gòu)的方法。
例如,
struct Date {
?????????????? short month;
?????????????? short day;
?????????????? long year;
};
定義 struct 時(shí),要確保所創(chuàng)建的類型是可讀的。
不要在不同的名稱空間中創(chuàng)建幾個(gè)不同的同名結(jié)構(gòu),會(huì)使 IDL 的用戶糊涂。
識(shí)別聯(lián)合
聯(lián)合是 C 聯(lián)合類型和 switch 語句的混合物。
聯(lián)合必須有類型標(biāo)記字段。
一次只能有一個(gè)聯(lián)合成員是活動(dòng)的,并且可以從其識(shí)別名稱來確定該成員。
例如,
enum PressureScale{customary,metric};
?
union BarometricPressure switch (PressureScale)
{
?case customary :
??? float Inches;
?case metric :
?default:
??? short CCs;
};
?
在以上示例中,如果識(shí)別名稱是 metric,或者使用了不能識(shí)別的識(shí)別名稱值,那么 short CCs 就是活動(dòng)的。如果識(shí)別名稱是 customary,那么 float 成員 Inches 是活動(dòng)的。聯(lián)合成員可以是任何類型,包括用戶定義的復(fù)雜類型。
識(shí)別名稱類型必須是整數(shù)類型(short、long、long long 等,以及 char、boolean 或 enumeraton)。
常數(shù)定義
常數(shù)可以是整數(shù)、字符、浮點(diǎn)數(shù)、字符串、Boolean、octet 或枚舉型,
?不能是 any 類型或用戶定義的類型。
例如,
const float MeanDensityEarth = 5.522;????? // g/cm^3
const float knot = 1.1508;???????????????? // miles per hour
const char NUL = '