MIDL and ODL
The Microsoft Interface Definition Language (MIDL) now includes the complete Object Definition Language (ODL) syntax. This allows you to use the 32-bit MIDL compiler instead of Mktyplib.exe to generate a type library and optional header files for a COM application.
Note
When the documentation refers to an ODL file, this means a file that Mktyplib.exe can parse. When it refers to an IDL file, this means a file that the MIDL compiler can parse. This is strictly a naming convention. The MIDL compiler will parse an input file regardless of its file name extension.
The topics in this section discuss using the MIDL compiler and IDL files containing both IDL and ODL statements to generate type libraries:
- Generating a Type Library With MIDL
- Additional Files Required To Generate a Type Library
- Differences Between MIDL and MkTypLib
- ODL Language Features in MIDL
- Generating a Proxy DLL and a Type Library From a Single IDL File
Generating a Type Library With MIDL
The top-level element of the ODL syntax is the library statement (library block). Every other ODL statement, with the exception of the attributes that are applied to the library statement, must be defined within the library block. When the MIDL compiler sees a library block, it generates a type library in much the same way as MkTypLib does. With a few exceptions, described in Differences Between MIDL and MKTYPLIB, the statements within the library block should follow the same syntax as in the ODL language and MkTypLib.
You can apply ODL attributes to elements that are defined either inside or outside the library block. These attributes have no effect outside the library block unless the element they are applied to is referenced from within the library block. Statements inside the library block can reference an outside element either by using it as a base type, inheriting from it, or by referencing it on a line as shown:
<some IDL definitions including definitions for interface IFace and struct bar> [<some attributes>] library a { interface IFace; struct this_struct; ... };
If an element defined outside the library block is referenced within the library block, then its definition will be put into the generated type library.
The MIDL compiler treats the statements outside of a library block as a typical IDL file and parses those statements as it has always done. Normally, this means generating C-language stubs for an RPC application.
For more information about the general syntax for an ODL file see ODL File Syntax.
Additional Files Required To Generate a Type Library
In order to compile an IDL file that contains a library statement, the OLE and OLE Automation DLL files must be on your system. These files are automatically installed with Microsoft Windows NT/Windows 2000 or Windows 95.
Effective with Windows NT 4.0, Oleaut32.dll supports a richer format for 32-bit type libraries. MIDL looks for this DLL on the build computer; if the new version is present, MIDL generates a new-format type library, otherwise it generates an old-format type library.
Note for 16-bit developers
If your application must interoperate with 16-bit applications, you must use the old-format type library for compatibility. The MIDL command-line option /old overrides this default and directs the MIDL compiler to generate old-format type libraries even if the newer version of Oleaut32.dll is present.
Some of the base types that MkTypLib supports are not directly supported in MIDL. MIDL obtains definitions for these base types by automatically importing Oaidl.idl whenever it sees a library statement. You need to ensure that this file is somewhere in your include path. The Oaidl.idl file, and the files that it imports (Objidl.idl, Unkwn.idl, and Wtypes.idl) are automatically installed when you install the Platform SDK.
See Also
Marshaling OLE Data Types, /old, /new
Differences Between MIDL and MkTypLib
There are a few key areas in which the MIDL compiler differs from MkTypLib. Most of these differences arise because MIDL is oriented more toward C-syntax than MkTypLib.
In general, you will want to use the MIDL syntax in your IDL files. However, if you need to compile an existing ODL file, or otherwise maintain compatibility with MkTypLib, use the /mktyplib203 MIDL compiler option to force MIDL to behave like Mkktyplib.exe, version 2.03. (This is the last release of the MkTypLib tool.) Specifically, the /mktyplib203 option resolves these differences:
- typedef syntax for complex data types
In MkTypLib, both of the following definitions generate a TKIND_RECORD for "this_struct" in the type library. The tag "struct_tag" is optional and, if used, will not show up in the type library.typedef struct struct_tag { ... } this_struct; typedef struct { ... } that_struct;
If an optional tag is missing, MIDL will generate it, effectively adding a tag to the definition supplied by the user. Since the first definition has a tag, MIDL will generate a TKIND_RECORD for "this_struct" and a TKIND_ALIAS for "this_struct" (defining "this_struct" as an alias for "struct_tag"). Because the tag is missing in the second definition, MIDL will generate a TKIND_RECORD for a mangled name, internal to MIDL, that is not meaningful to the user and a TKIND_ALIAS for "that_struct". This has potential implications for type library browsers that simply show the name of a record in their user interface. If you expect a TKIND_RECORD to have a real name, unrecognizable names could appear in the user interface. This behavior also applies to union and enum definitions, with the MIDL compiler generating TKIND_UNIONs and TKIND_ENUMs, respectively.
MIDL also allows C-style struct, union , and enum definitions. For example, the following definition is legal in MIDL:struct my_struct { ... }; typedef struct my_struct your_struct;
- Boolean data types
In MkTypLib, the Boolean base type and the MkTypLib data type BOOL equate to VT_BOOL, which maps to VARIANT_BOOL, and which is defined as a short . In MIDL, the Boolean base type is equivalent to VT_UI1, which is defined as an unsigned char , and the BOOL data type is defined as a long. This leads to difficulties if you mix IDL syntax and ODL syntax in the same file while still trying to maintain compatibility with MkTypLib. Because the data types are different sizes, the marshaling code will not match what is described in the type information. If you want a VT_BOOL in your type library, you should use the VARIANT_BOOL d ata type. - GUID definitions in header files
In MkTypLib, GUIDs are defined in the header file with a macro that can be conditionally compiled to generate either a GUID predefinition or an instantiated GUID. MIDL normally puts GUID predefinitions in its generated header files and GUID instantiations only in the file generated by the /iid switch.
The following differences in behavior cannot be resolved by using the /mktyplib203 switch:
- Scope of symbols in an enum declaration
In MkTypLib the scope of symbols in an enum is local. In MIDL, the scope of symbols in an enum is global, as it is in C. For example, the following code will compile in MkTypLib, but will generate a duplicate name error in MIDL:typedef struct { ... } a; enum {a=1, b=2, c=3};
- Scope of public attribute
If you apply the public attribute to an interface block, MkTypLib treats every typedef inside that interface block as public. MIDL requires that you explicitly apply the public attribute to those typedefs that you want public. - Importlib search order
If you import more than one type library, and if these libraries contain duplicate references, MkTypLib resolves this by using the first reference that it finds. MIDL will use the last reference that it finds. For example, given the following ODL syntax, library C will use the GOO typedef from library A if you compile with MkTypLib, and the GOO typedef from library B if you compile with MIDL:[...]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 }
The appropriate workaround for this is to qualify each such reference with the correct import library name, like this:
typedef struct tagBAA
{A.MOO y;}BAA
- VOID data type not recognized
MIDL recognizes the C-language void data type and does not recognize the OLE Automation VOID data type. If you have an ODL file that uses VOID , place this definition at the top of the file:#define VOID void
- Exponential notation
MIDL requires that values expressed in exponential notation be contained within quotation marks. For example, "-2.5E+3" - LCID values and constants
Normally MIDL does not consider the LCID when parsing files. To force this behavior for a value, or if you need to use locale-specific notation when defining a constant, enclose the value or constant in quotation marks.
See Also
/mktyplib203, /iid, Marshaling OLE Data Types
ODL Language Features in MIDL
The following topics list the Object Description Language (ODL) attributes, keywords, statements, and directives that are now part of the Microsoft Interface Definition Language (MIDL).
- ODL Attributes
- ODL Keywords, Statements, and Directives
ODL Attributes
[appobject]
[hidden]
[propput]
[bindable]
[id]
[propputref]
[control]
[immediatebind]
[public]
[default]
[in]
[readonly]
[defaultvalue]
[lcid]
[requestedit]
[displaybind]
[licensed]
[restricted]
[dllname]
[nonextensible]
[retval]
[dual]
[odl]
[source]
[entry]
[oleautomation]
[uuid]
[helpcontext]
[optional]
[vararg]
[helpfile]
[out]
[version]
[helpstring]
[propget]
ODL Keywords, Statements, and Directives
coclass
library
dispinterface
module
enum
struct
[importlib]
typedef
interface
union
For information on how to marshal OLE Automation types, such as BSTR, VARIANT, and SAFEARRAY , see Marshaling OLE Data Types .
Generating a Proxy DLL and a Type Library From a Single IDL File
You can use a single IDL file to generate both the proxy stubs and header files for marshaling code, and a type library. You do this by defining an interface outside the library block and then referencing that interface from inside the library block, as shown in this example:
//file: AllKnown.idl [ object, uuid(. . .), <other interface attributes> ] interface IKnown : IUnknown { import "unknwn.idl"; <declarations, etc. for IKnown interface go here> }; [ <library attributes> ] library KnownLibrary { //reference interface IKnown: interface IKnown; //or create a new class: [ <coclass attributes> ] coclass KnowMore { interface IKnown; }; };