Next: Creating COM objects with GNAT, Previous: Using COM objects with GNAT [Contents][Index]

## 4 Creating Type Libraries for COM objects

The first step to building a COM object with GNAT is the construction of a type library. This can be done by compiling a specification created in Microsoft IDL (Interface Definition Language) and using Microsoft’s MIDL compiler. The IDL specification must be constructed to contain a type library definition and it is highly recommended that it conform to the ole automation specifications. It is possible to create with GNAT COM objects that use any valid IDL that would work with other languages.

This documentation details an ideal IDL for easy implementation in Ada. See the GNAT example `gnatexample.idl` for the complete example.

Microsoft IDL is a superset of DCE RPC IDL which is very similar in syntax to C. IDL files for COM objects used with GNAT will generally take the form of interface definitions followed by a type library block that defines the composition of each COM object in the library.

IDL files should begin with the following two lines that import needed specifications:

    import "unknwn.idl";
    import "oaidl.idl";

IDL uses brackets to contain attributes and braces to define blocks. For example:

    [
            object,
            uuid(45F9F483-787C-11d3-821C-52544C1913DE),
            helpstring("Statistics on object interface"),
            oleautomation
    ]
    interface IGNATStat : IUnknown
    {
            [
                    helpstring("Return number of times methods were called")
            ]
            HRESULT Calls([out] int *NumberOfTimes);
    }

Each interface block should have the attributes object, uuid, helpstring, and oleautomation. If this interface is to also support dynamic use through `IDispatch` for script languages, it should also be marked with the attribute dual. The Object attribute designates that this is a COM interface and not an RPC interface. The uuid attribute provides the univeral unique ID that this interface will be known as and must be unique for each uuid attribute used. This number can be generated using tools such as `uuidgen` or `guidgen` from the Microsoft SDK, or by a call to the Win32 API function `CoCreateGuid`. The helpstring attribute allows type library browsers and binding generators to display the help string that is set. OleAutomation tells the MIDL compiler to insure that the interface conforms to Ole Automation specifications insuring the type library marshaling can be used for the object (see the section on creating COM objects with GNAT).

Every interface must derive from either `IUnknown`, `IDispatch` or any other child of `IUnknown` in order to be used with COM objects. Objects that are derived from `IDispatch` should include the attribute dual to the interface. Interfaces are defined using the interface key word followed by the interface name then a colon and the parent interface. The methods of the interface are then defined in the interface block between brackets.

Each method of the interface may contain a helpstring attribute in the same manner as the interface. If the interface is derived from `IDispatch`, you may optionally add the attribute ID to set its dispatch ID, an ID used for dynamic invocation of the interface. If no ID is given, MIDL will assign one automatically. For example:

    [
     id(1),
     helpstring("Audio Alert")
    ]
    HRESULT Beep();

Every method must return a type called an `HRESULT` that returns the success or failure of the method. Parameters if each method need to include an attribute of in or out. Out parameters must be pointer types. Allowable types are `boolean`, `unsigned char`, `double`, `float`, `int`, `long`, `short`, `BSTR`, `CURRENCY`, `DATE`, `SCODE`, `enum`, `IDispatch*`, `IUnknown*`, `SAFEARRAY` of any OLE automation type, and pointers to any of the above types. For example:

    [
     id(2),
     helpstring("Display Message Box")
    ]
    HRESULT MessageBox([in] BSTR Message);

Following all interfaces definitions, a library block should be created with the attributed uuid, helpstring, and version. With in the library block the first statement should be the following:

    importlib("stdole32.tlb");

This imports the standard system library of OLE automation types. Following a line is added for each interface to import it in to the library. For example:

    interface IGNATMessage;
    interface IGNATStat;

Once the interfaces are now part of the library COM objects are defined that use the available interfaces using coclass blocks. Each block should have the attributes uuid and helpstring. With in the block each interface is listed and one interface should be chosen as the default interface. For example:

    [
           uuid (45F9F481-787C-11d3-821C-52544C1913DE),
           helpstring("GNAT Example Class")
    ]
    coclass GNATCOMClass
    {
           [default] interface IGNATMessage;
           interface IGNATStat;
    }

After compiling the IDL file using MIDL, only the .tlb file will be used in creating the COM object with GNAT.

Next: Creating COM objects with GNAT, Previous: Using COM objects with GNAT [Contents][Index]