MIDL 與 MkTypLib 之間的差異

注意

Mktyplib.exe工具已過時。 請改用 MIDL 編譯器。

 

MIDL 編譯器有幾個主要區域與 MkTypLib 不同。 大部分的差異都是因為 MIDL 比 MkTypLib 更向 C 語法導向。

一般而言,您會想要在 IDL 檔案中使用 MIDL 語法。 不過,如果您需要編譯現有的 ODL 檔案,或維護與 MkTypLib 的相容性,請使用 /mktyplib203 MIDL 編譯器選項來強制 MIDL 的行為類似 Mkktyplib.exe 2.03 版。 (這是 MkTypLib 工具的最後一個版本。) 具體而言, /mktyplib203 選項可解決這些差異:

  • 複雜資料類型的 typedef 語法

    在 MkTypLib 中,下列兩個定義都會在類型程式庫中產生 「this_struct」 的TKIND_RECORD。 標籤 「struct_tag」 是選擇性的,如果使用的話,就不會顯示在類型程式庫中。

    typedef struct struct_tag { ... } this_struct;
    typedef struct { ... } that_struct;
    

    如果遺漏選擇性標籤,MIDL 將會產生它,有效地將標記新增至使用者所提供的定義。 由於第一個定義具有 標記,MIDL 會產生 「this_struct」 的TKIND_RECORD,以及 「this_struct」 (定義 「this_struct」 作為 「struct_tag」 ) 別名的TKIND_ALIAS。 因為第二個定義中遺漏了 標記,所以 MIDL 會針對 MIDL 內部的受管理名稱產生TKIND_RECORD,對使用者而言沒有意義,TKIND_ALIAS 而且對 「that_struct」 而言沒有意義。

    這對類型程式庫瀏覽器可能會造成影響,這些瀏覽器只會在其使用者介面中顯示記錄的名稱。 如果您預期TKIND_RECORD具有實際名稱,則使用者介面中可能會顯示無法辨識的名稱。 此行為也適用于 聯集列舉 定義,而 MIDL 編譯器會分別產生TKIND_UNIONs和TKIND_ENUMs。

    MIDL 也允許 C 樣式 的結構等位列舉 定義。 例如,下列定義在 MIDL 中是合法的:

    struct my_struct { ... };
    typedef struct my_struct your_struct;
    
  • Boolean 資料類型

    在 MkTypLib 中, 布林 基底類型和 MkTypLib 資料類型 BOOL 等於VT_BOOL,其對應至VARIANT_BOOL,而其定義為 簡短。 在 MIDL 中, 布林 基底類型相當於VT_UI1,定義為 不帶正負號的字元,而 BOOL 資料類型則定義為 long。 如果您在相同的檔案中混合 IDL 語法和 ODL 語法,但仍嘗試維持與 MkTypLib 的相容性,這會導致困難。 因為資料類型的大小不同,所以封送處理常式代碼與類型資訊中所述的內容不符。 如果您想要在類型程式庫中VT_BOOL,您應該使用 VARIANT_BOOL 資料類型。

  • 標頭檔中的 GUID 定義

    在 MkTypLib 中,GUID 定義于標頭檔中,具有可有條件地編譯以產生 GUID 預先定義或具現化 GUID 的宏。 MIDL 通常會將 GUID 預先定義放在其產生的標頭檔,以及 GUID 具現化只會放在 /iid 參數所產生的檔案中。

使用 /mktyplib203 參數無法解析下列行為差異:

  • 區分大小寫

    MIDL 區分大小寫,OLE Automation 則不區分大小寫。

  • 列舉宣告中的符號範圍

    在 MkTypLib 中,列舉中的符號範圍是本機的。 在 MIDL 中,列舉中的符號範圍是全域的,因為它在 C 中。例如,下列程式碼會在 MkTypLib 中編譯,但在 MIDL 中會產生重複的名稱錯誤:

    typedef struct { ... } a;
    enum {a=1, b=2, c=3};
    
  • 公用屬性的範圍

    如果您將 公用 屬性套用至介面區塊,MkTypLib 會將該介面區塊內的每個 typedef 視為公用。 MIDL 要求您明確地將 公用 屬性套用至您想要公用的 typedef。

  • Importlib 搜尋順序

    如果您匯入多個類型程式庫,而且如果這些程式庫包含重複的參考,MkTypLib 會使用找到的第一個參考來解決此問題。 MIDL 會使用其找到的最後一個參考。 例如,假設有下列 ODL 語法,如果使用 MkTypLib 進行編譯,則程式庫 C 會使用程式庫 A 的 MOO typedef,以及使用 MIDL 編譯時,來自程式庫 B 的 MOO typedef:

    [...]library A
    {
        typedef struct tagMOO
        {...}MOO
    }
    
    [...]library B
    {
        typedef struct tagMOO
        {...} MOO
    }
    
    [...]library C
    {
        importlib (A.TLB)
        importlib (B.TLB)
        typedef struct tagBAA
        {MOO y;}BAA
    }
    

    適當的因應措施是使用正確的匯入程式庫名稱來限定每個這類參考,如下所示:

    typedef struct tagBAA
        {A.MOO y;}BAA
    
  • 無法辨識 VOID 資料類型

    MIDL 會辨識 C 語言 void 資料類型,而且無法辨識 OLE Automation VOID 資料類型。 如果您有使用 VOID 的 ODL 檔案,請將此定義放在檔案頂端:

#define VOID void '''

  • 指數標記法

    MIDL 要求以指數標記法表示的值包含在引號內。 例如,「-2.5E+3」

  • LCID 值和常數

    通常 MIDL 不會在剖析檔案時考慮 LCID。 若要強制這個值的行為,或如果您需要在定義常數時使用地區設定特定的標記法,請將值或常數括在引號中。

如需詳細資訊,請參閱 /mktyplib203/iidMarshaling OLE 資料類型