How do I invoke the MIDL compiler to generate a .TLB file (type library) from an .IDL file?
Asked Answered
P

1

7

I am struggling with something seemingly super-simple: I'd like to use the MIDL compiler to generate a type library (.tlb file) from a .idl file. However, I just can't get MIDL to generate a .tlb file.

This is my Foo.idl:

import "unknwn.idl";

[object, uuid(400075B9-4BD6-45A5-B8B7-9DA0CF7B9B13)]
interface IFoo : IUnknown
{
    HRESULT DoFoo([in] int arg, [out, retval] int *result);
}

This is how I invoke the MIDL compiler:

midl Foo.idl /tlb Foo.tlb

Which writes the following output to the console:

Microsoft (R) 32b/64b MIDL Compiler Version 7.00.0555
Copyright (c) Microsoft Corporation. All rights reserved.
Processing .\Foo.idl
Foo.idl
Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.idl
unknwn.idl
Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\wtypes.idl
wtypes.idl
Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\basetsd.h
basetsd.h
Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\guiddef.h
guiddef.h

The MIDL compiler produces three files: Foo.h, Foo_i.c, Foo_p.c… but no Foo.tlb. Am I misunderstanding something, or what has gone wrong here?

Perloff answered 15/5, 2015 at 21:36 Comment(2)
Only stuff defined or referenced in library block is placed into a TLB file. Further, interfaces you want to place into a TLB should be dual or oleautomation or dispinterface. A TLB format can only accurately represent an automation-compatible interface. int is not an automation type - make it a long.Toting
@IgorTandetnik: Thank you for your suggestions. Where do you guys take all that good knowledge from!? Could you by chance recommend a resource where I could read up on the "a TLB format can only accurately represent an automation-compatible interface" bit?Perloff
S
10

The .idl file requires a library{} block before it will generate a type library. Inside this block you'll need to declare the types that need to be present inside the library. A normal library only has coclass definitions in the library section, midl automatically injects any interfaces that the coclasses use.

Getting just the interface requires moving it inside the library block:

[
  uuid(34DC0E7C-37C1-41C1-B3FD-1755A0396308),
  version(1.0),
]
library MyLibrary
{
    importlib("stdole2.tlb");

    [object, uuid(400075B9-4BD6-45A5-B8B7-9DA0CF7B9B13)]
    interface IFoo : IUnknown {
        HRESULT DoFoo([in] long arg, [out, retval] long *result);
    };
};

Use your own uuid, version number and name for the library. The importlib voodoo ensures that the definitions for IUnknown and GUID don't get embedded in the type library as well.

Shibboleth answered 16/5, 2015 at 0:21 Comment(1)
Getting just the interface requires moving it inside the library block A declaration, as in interface IFoo;, of an interface defined outside the block should be sufficient.Toting

© 2022 - 2024 — McMap. All rights reserved.