Microsoft接口定義語言

Microsoft接口定義語言（Microsoft Interface Definition Language；縮寫：MIDL）是微軟的基於文本的接口描述語言。擴展自DCE/RPC IDL用於微軟的組件對象模型（Component Object Model）。它的編譯器是MIDL.exe（隨Microsoft Windows SDK發行）。MIDL用於遠程過程調用（RPC）的接口、DCOM接口、OLE自動化的類型庫等的描述.

## 簡介

每個IDL文件包含一個或多個interface定義。每個interface定義由interface頭部與interface體組成。interface頭部給出了接口的整體資訊；如果含關鍵字object，表示這是一個COM接口，否則表示這是一個DCE RPC接口。interface體給出了所有需要暴露的資訊。

IDL文件中一個接口的結構資訊：

```idl4
[ //header

  //Interface attributes go here.

]
interface INTERFACENAME //body

{
//The interface body goes here.

}
library TyeLibraryFileName
{
  //Type library Information

}
```

IDL文件接口示例：

```idl4
[
    object,
    uuid(C0E20128-DB19-4DB3-BCA1-24595E5E24A8),
    dual,
    nonextensible,
    helpstring("IConfig Interface"),
    pointer_default(unique)
]
interface ILogManager : IDispatch
{
    [id(1), helpstring("Initializes ILogManager")] HRESULT Initialize([in] IConfig* Config);

    [id(2), helpstring("Logs MemberClaims")] HRESULT LogMemberClaims([in] IMember* Member);

    [id(3), helpstring("Logs ILogData to specified destination")] 
            HRESULT Log([in] ILogData* LogData);

};
library MyTypeLibraryFileLib
{
 [
  uuid(B3F6C9C4-26AE-451B-9788-75F6C648DBF4),
  helpstring("LogManager Class")
 ]
 coclass LogManager
 {
  [default] interface ILogManager;
 }; 
}
```

類型庫用於向編譯器提供關於類、接口、枚舉等的COM對象或COM接口的資訊。類型庫是二進位文件。MIDL編譯器處理IDL文件並創建類型庫文件、頭文件、proxy文件。例如：

```
midl myfilectl.idl /tlb myfilectl.tlb /h
```

其中/h產生C++頭文件。

MIDL編譯器編譯name.idl默認產生的文件，對於RPC接口為:

```
Client stub (name_c.c)
Server stub (name_s.c)
Header file (name.h)
```

對於COM接口默認產生的文件:

```
Interface proxy/stub file (name_p.c) 给客户/服务器的surrogate entry points
Interface header file (name.h) 包含IDL文件中定义的接口的类型定义与函数声明，以及stub调用的子例程的前向声明。
Interface UUID file (name_i.c) 接口ID文件，定义IDL文件中的每个接口的GUID
类型库文件(name.tlb)
Dlldata.c 创建proxy/stub DLL所需要的数据
```

如果接口屬性列表中有local屬性，編譯進產生接口的頭文件, Name.h.

## 歷史

MIDL 3.0版支持按照類似於C♯的格式寫idl文件。這要求使用Microsoft Windows SDK 10.0.17134.0版或以上，其所包含的midl.exe 為8.01.0622版或以上，編譯時使用/winrt選項。接口中的非local的成員函數返回類型只能是HRESULT 或 SCODE，早於3.0的版本還允許返回類型為void，但這種3.0版本中將編譯報錯。

## 語言內容

接口可以前向聲明，以便被引用。

類型定義(typedef)、construct聲明、import指令（類似於C語言預處理器include指令），可以出現在interface體的外部。IDL文件的這些定義都會出現在產生的頭文件中；所有接口的所有過程都會被創建stub例程。

### MIDL數據類型

陣列定義遵從C語言的標準，陣列下界必須為0。一對方括號內如果只有一個數，表示陣列下界為0上界為N-1；如果方括號內為*號，表示下界為0上界在運行時確定；lower...upper明確給出上下限。多維陣列只有最左維可以不在編譯時指定。

封裝的聯合類型（encapsulated union）是指類型的通過switch定義的判別數據成員（discriminant）也被封裝在類型中。如下例：

```idl4
typedef union _S1_TYPE switch (long l1) U1_TYPE 
{ 
    case 1024: 
        float f1; 
    case 2048: 
        double d2; 
} S1_TYPE; 
```

```cpp
/* 在产生的头文件中： */ 
typedef struct _S1_TYPE 
{ 
    long l1; 
    union 
    { 
        float f1; 
        double d2; 
    } U1_TYPE; 
} S1_TYPE;
```

### 類型庫

類型庫是二進位文件(.tlb)包含了一個ActiveX應用程式暴露的類型與對象的資訊。可包括：

- 數據類型資訊，如：aliases, enumerations, structures, unions.
- 對象描述，每一個這樣的描述稱作typeinfo。如：module, interface, IDispatch interface (dispinterface), component object class (coclass). 可以理解接口是抽象類，coclass是接口的物理實現類。
- 引用別的類型庫的類型描述。

類型庫可以是midl編譯產生的單獨的二進位文件(.tlb，表示type library)。也可以用資源編譯器(rc.exe)把.tlb文件增加到DLL或exe文件中。帶有1個或多個類型庫資源的DLL典型具有文件擴展名.olb (object library). tlb文件在資源文件(.rc)中必須寫成如下形式，帶有整數辨識符、類型為TypeLib：

```
1 typelib mylib1.tlb
2 typelib mylib2.tlb
```

把tlb登記在Windows註冊表，可以用.NET FRAMEWOK帶有的regtlibv12.exe，通常在這樣的目錄下：

```
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe
```

各種類型庫工具（如編譯器、object browser等）通過 ITypeLib 這樣的接口訪問二進位類型庫資訊。

類型庫描述語言是ODL，最頂層語法結構是library語句。

MIDL的數據類型中, boolean基礎類型等價於VT_UI1；BOOL數據類型被定義為long；如果希望使用VT_BOOL，那應該用VARIANT_BOOL數據類型。

下述代碼裝入並在Windows註冊表中註冊一個類型庫：

```cpp
ITypeLib *pTypeLib;
HRESULT hr;
hr = LoadTypeLibEx("example.tlb", REGKIND_REGISTER, &pTypeLib);
if(SUCCEEDED(hr))
{
    pTypeLib->Release();
} else {
    exit(0); // Handle errors here.
}
```

## 外部連結

- Microsoft Interface Definition Language 3.0 reference - Windows UWP applications | Microsoft Docs