ArcGIS SDK  

Extending ArcObjects

Creating type libraries using IDL

In this section

  1. About type libraries
  2. Creating a type library for a VC++ component
  3. Creating an external type library for a component created in VB

About type libraries

A type library is an essential part of a component, providing information to the compiler about the classes, interfaces, enumerations, and so on, included in the component.

Type library files have the extension .tlb, although type libraries can also be embedded into other files, for example, object libraries (.olb) or DLLs. Throughout this section, the term type library may refer to either a .tlb file or to a library contained in another file.

ArcObjects object libraries

Type information for ArcObjects components is contained in a number of object libraries. Each area of ArcObjects functionality is contained in a different object library—for example, the ArcMap user interface classes, interfaces, and enumerations are defined in the esriArcMapUI.olb object library.

Why are type libraries necessary?

You need to reference a type library to declare variables or implement interfaces using the types defined in the library. The type library is then used when your component is compiled to check the type information to allow early binding of types.

Type libraries also allow type-dependent design-time features to function correctly, such as VB's intellisense and parameter information.

How are type libraries created?

When you create a component, type library information should be created too. The VB compiler automates the process of creating a type library, embedding type library information within your compiled DLL or EXE file.

If you are developing in VC++, however, you create Interface Definition Language (IDL) files to define the contents of the type library, which are compiled into a separate .tlb file when the project is compiled.

Why should I use IDL to create a type library?

Type libraries are aimed at allowing development to cross programming language boundaries. However, certain incompatibilities exist between the type library information that is created by default and that can be implemented by different development environments.

Although COM components are accessible from any language, a type library may be required to make the information contained in the component accessible to other developers.

Regardless of the environment you are using, you can ensure your type library is standardized by writing your type library information in IDL and compiling this into a type library.

You can create an external type library, regardless of the development environment you are using.

This could be necessary if you expect your component to be called by or implemented in other environments by other developers within or outside your development team. Multiple type libraries may also be used as an organizational tool to separate interfaces, structures, and enumerations from coclass definitions or to separate public from private information.

This section covers how you can create a type library by writing IDL, both for a VB and a VC++ project, and the reasons why you might decide to do this. It covers certain issues of writing IDL that can help you ensure your components can act as a server to a variety of development environments.

The instructions in this section include the use of the Microsoft Interface Definition Language (MIDL) compiler, and optionally the OLE COM Object Viewer utility (OLE View). Earlier in this chapter, in the 'Choosing your development environment' section, you can find information on how you can get these utilities.

Viewing a type library

You can investigate the contents of a type library in many ways.

Type libraries can be viewed in many different ways, for example, the Microsoft OLE View utility, the ESRI Object Browser, and the developer help system.

The ESRI libraries are described in both VC++ and VB syntax in the ArcObjects component help system.

The Microsoft OLE View utility can be used to view the contents of a type library and unpack the IDL code it contains. As well as .tlb files, this utility can view the type library information inside a DLL or EXE, an ActiveX control, or an object library file (.olb).

The ESRI Object Viewer can also be used to view the contents of type libraries in these files. The declarations can be viewed as IDL, as they would appear on an object diagram, or using VB syntax.

If you are a VB developer, you may be most familiar with the VB Object Browser, which shows a VB interpretation of a type library—for more information on what this implies, see the following section on defining interfaces in IDL.

About IDL files

IDL is a language that can be used to describe COM interfaces and other data types. Although based on the C language, it can only be used to define data types—it cannot be used to implement interfaces or create classes. For more information on IDL, see the bibliography. Essential IDL by Martin Gudgin may be particularly useful for programmers working in VB.

The basic 'unit' of IDL is composed of two parts. First, a section within square brackets contains attributes, which define things such as a Globally Unique IDentifier (GUID), a version number, helpstring, and help context ID number.

[
  uuid(764EDFE5-09A7-11D6-8A8E-00104BB6FCCB),
  version(1.0),   helpcontext(16),
  helpstring("DisplayCommands 1.0 Type Library")
]

This section is directly followed by a named entity to which these attributes apply. The section begins with the entity name, followed by a section within curly brackets, which defines the entity in detail.

library DISPLAYCOMMANDSLib
{
  importlib("stdole32.tlb");    // Import libraries containing 
  importlib("stdole2.tlb");     // standard COM API calls.
  importlib("C:\Program Files\ArcGIS\Com\esriFramework.olb");
  [
    object,
    uuid(764EDFF1-09A7-11D6-8A8E-00104BB6FCCB),
    helpstring("IZoomIn Interface"),
    pointer_default(unique)
  ]
  interface IZoomIn : IUnknown

In the following pages, you can find more information about issues you may face when creating type libraries in VB and in VC++ and how you can create more language-independent type libraries for your components.


Creating a type library for a VC++ component

As a VC++ programmer you should already be familiar with the process of creating external type libraries by using IDL to define an interface and the MIDL compiler to compile the IDL to a type library file.

If you have experience with Active Template Library (ATL), you may have set MIDL compiler options via the Project Settings dialog box; although as IDL is integrated into the project environment, you may not have been specifically aware of using it.

The MIDL compiler is used by the VC++ environment to create a type library; the MIDL tab of the Project Settings dialog box is used to adjust MIDL compiler settings.

This section presents a brief review of the steps to turn IDL into a type library for your project.

Creating an IDL file

The basic creation and editing of an IDL file using the ATL COM AppWizard is described in Development Environments, COM, Visual C++ section of the developer help system.

In summary, there are two steps. First, create a new project using the ATL COM AppWizard. Then use the ATL Object Wizard to add objects to the project, choosing Simple Object as the template. The interface type you choose, dual or custom, will depend on the intended usage of the component—see the 'Coding Interfaces' section earlier in this chapter for more information. At this point, you have a project containing a basic IDL file defining a library.

Adding members to the IDL file

You can easily add interfaces and implement members on your new class by using the context menus on the Visual C++ ClassView. However, you should check the IDL file to make sure it matches what is defined in your C++ code. In particular, check the following.

Editing IDL for client neutrality

If you are creating a component in VC++ that may be used in other environments, for example, the ArcGIS VBA environment or VB, you should be aware that not every environment supports all the items you can define in VC++ and IDL.

First, you will need to restrict the data types publicly used in your component to those supported in the target environment. Other issues you may want to consider include:

For more information on how to make these changes, read the 'Editing IDL' appendix. You may also want to refer to the IDL references included in the bibliography.

Compiling the IDL to a Type Library

When you build your VC++ project, referenced IDL files are compiled to a .tlb file. The compiler switches used can be modified, if necessary, from the MIDL tab of the Project Settings dialog box.

Removing type library information from the DLL

By default, type information is also included in the DLL as a resource. This can be removed. ArcObjects DLLs contain no type information, which is instead contained centrally in the object libraries. You may want to remove type library information from your DLL if you have a particular requirement to reduce the size of the DLL, or to keep type information separate from your implementation code.

You can compile a DLL without type information by ensuring the type library is not included as a resource. From the View menu in Visual Studio, open the Resource Includes dialog box and remove the type library directive. It will look something like the following:

1 TYPELIB "ZoomInSample.tlb"

You can also remove this line directly from the resource (.rc) file if you open it up as a text file.

Alternatively, you can leave type information in your DLL, but prevent that information from being entered to the system registry when the DLL is registered. You can do this by changing the RegisterSever call in the DllRegisterServer function of your project to pass a parameter of FALSE.

Type libraries are not always needed at runtime, and therefore, are not always present on an install to a user machine. However, if your component is dual interface, the type library is needed at runtime to turn IDispatch calls into v-table calls. For this reason, if your component is dual interface, you should not remove the type library information from the component DLL.


Creating an external type library for a component created in VB

As a VB developer, you would usually define an interface in a public noncreatable class module by stubbing out the methods and properties required. The interface is then inherited in a creatable class module using the Implements keyword.

How VB creates type library information

When a project is compiled, VB includes type library information in the component's binary file (DLL or EXE). VB hides the details of COM implementation from developers, and many 'under the covers' differences are hidden within the type library. Although any clients also written in VB will be able to call or implement this interface with no problems, developers in other environments may encounter problems when trying to use or implement the interfaces defined in this component.

By default, VB compiles type library information into the component binary files.

For example, VB prefixes all VB-defined interface names with an underscore—for a class module (defining an interface) named IZoomIn, the name in the type library will be _IZoomIn. VB clients will automatically remove this underscore; however, clients written in other languages may need to use the name as specified in the type library.

Interfaces created in VB are always dual—they will inherit from both IUnknown and IDispatch.

The VB compiler also automatically defines a hidden, default interface for each class, containing all the public members of the class. Open a VB DLL in OLE View to see the changes that have been made to class names, and so on.

VC++ programmers may use a VB component by using these internal names or by redefining the names using the import. However, neither approach is ideal, especially if the component is to be distributed to third parties.

If your VB component implements a custom interface, you may need to create an external type library to provide information about the interface to any non-VB clients that want to use it. This is because, although VB includes type library information in compiled projects automatically, it is nonstandard, and may cause problems in other development environments.

Alternatively, the VB programmer may provide a separate type library for the component, allowing all clients to access the VB component on equal terms.

Creating an external type library for a VB component

If you are familiar with IDL, you can go ahead and write your type definitions in IDL and compile the file into a type library (.tlb) file.

If you are not familiar with IDL, you can use VB and the Microsoft Visual Studio tools to help write your IDL file for you.

In summary, the VB environment is used in the usual way to stub out the interfaces in the component and compile a DLL, then the OLE View utility unpacks the type library from this component. This information can be copied to an IDL file, then the MIDL compiler is used to compile the IDL file into an external type library, which can be used by other development environments.

To create an external type library for a VB component, you need to define a type library using IDL. There are utilities available, which can help you create your IDL.

The following steps describe how to create an external type library for VB by using OLE View and the MIDL compiler.

Creating the basic IDL file with VB and OLE View

Follow the steps below to create an IDL file for a VB project.

  1. In VB, create a new ActiveX DLL project. Define your required interfaces as usual—use a public noncreatable class module and add public properties and methods. For example, add a class module called IMyInterface, and define a property:
    [Visual Basic 6]
    Public Property Get MyValue() As Integer
    End Property
  2. Compile the component.
  3. From the Start menu, navigate to Microsoft Visual Studio Tools and open the OLE View utility.
  4. In OLE View, click the View TypeLib menu option, navigate to the component you just built, then click Open.

    An .idl file for your component will be displayed in the viewer, looking something like that shown below.

    // Generated .IDL file (by the OLE/COM Object Viewer)
    // typelib filename: MyProject.dll
    [
      uuid(E955ED36-19E2-4EE0-8C1C-841D845D00A0), version(1.0)
    ]
    library MyProject
    {
      // TLib :     // TLib : OLE Automation : {00020430-...46}
      importlib("stdole2.tlb");
      
      // Forward declare all types defined in this typelib
      interface _IMyInterface;
      [
        odl, uuid(4509BC45-7691-4B6A-81C6-2C7EAF0C982B),
        version(1.0), hidden, dual, nonextensible, oleautomation
      ]
      interface _IMyInterface : IDispatch {
       id(0x68030000), propget]
       HRESULT MyValue([out, retval] short* );
      };
      [
        uuid(FBC41564-3748-445D-A11D-3343178373AD),
        version(1.0), noncreatable
      ]
      coclass IMyInterface {
       [default] interface _IMyInterface;
      };
    };
  5. Copy the IDL to a text editor and save the file using the suffix .idl.

Editing the IDL from OLE View

If you try to compile your new IDL file as it stands, it is likely that the MIDL compiler will give errors. If it should compile successfully, you will find that the contents of the type library are not exactly as you might expect. As you can see in the IDL shown above, the interface name IMyInterface is changed to _IMyInterface, and there is a coclass definition for the IMyInterface, which was the interface you defined in a class module.

After creating your IDL file with the OLE View utility, you will need to edit the IDL by hand before compiling it to a type library.

Before compiling the type library, you will need to make changes to the IDL file, which you can do in any plain text editor, for example, Notepad.

These changes will correct syntax and changes made by the VB compiler, and also the differences between OLE View interpreted IDL and IDL syntax required by the MIDL compiler. Briefly, these changes include:

For more information on how exactly to make these changes, read the 'Editing IDL'appendix; you may also want to refer to the IDL references included in the bibliography.

Creating a type library from the IDL

After editing the IDL, you can create a type library. Use the MIDL compiler (midl.exe) to compile the .idl file. (Note that the "/h" switch will produce a C/C++ header file as well.)

The MIDL compiler is used to turn the IDL you have written into a type library.

If you received syntax errors, check the Visual Studio online reference for more information on IDL and the MIDL compiler. Check that any changes you made to the IDL conform to the syntax correctly.

You can place the commands in a batch file to make it easier to rerun your compilation as you fix syntax errors, as shown below.

REM Set variables to point to the correct folders on your computer.
SET MIDLDir="C:\Program Files\Microsoft Visual Studio\VC98\Bin"
SET IDLFile="C:\Temp\IDL\MyLayer.idl"
SET TLBFile="C:\Temp\IDL\MyLayer.tlb"
 
REM Navigate to the MIDL directory
chdir /d %MIDLDir%
 
REM run the MIDL compiler producing a TLB file
midl "%IDLFile%" /tlb "%TLBFile%"
pause

A batch file is useful to rerun your MIDL compiler commands, as you may need to recompile a number of times before you eliminate all syntax errors.

You now have a type library providing type information about your VB component that you can call and implement in VC++ or other COM-compliant environments.

Implementing the interface in your VB component

You can now return to VB and use this type library in your component.

  1. Open the project where you want to create your component. Add a reference to the type library you just created by clicking Project, clicking References, and navigating to the .tlb file.
  2. In the class module, as appropriate, implement the interfaces you just defined in your type library by using the Implements keyword, ensuring the interface name is fully referenced.
    [Visual Basic 6]
    Implements MyLibraryName.IMyInterface
  3. Now stub out and complete the implementation of the interface members.
  4. Ensure that you compile your component using this new reference. If you used the same project to define your interface in the first place, make sure you remove the interface modules.

By referencing the new standalone type library in your project, you can implement the interfaces it contains in VB classes, and use any structures or enumerations you defined.

In VB, a coclass cannot be defined based on IDLany coclass definitions in the IDL cannot be reused in VB. However, enumerations and structures defined in a type library can be used directly in VB code, as long as they contain compatible data types.

Note also that VB is unable to implement existing outbound interfaces—for example, a VB component cannot be a source of events defined by the existing IActiveViewEvents interface.


Back to top