2.4 Type Libraries

only for RuBoard - do not distribute or recompile

2.4 Type Libraries

The interface and co-class definitions are stored in a special file called a type library . In the case of Animals.dll , VB creates the type library automatically and stores it as a resource inside the component. But you can also create your own type libraries. The type libraries that you create can then be referenced from VB. In fact, since VB does not allow us to create type information that is suitable for our needs in developing shell extensions, we're going to have to create our own type library. But before we do that, we will talk about what a type library is and what goes inside of one.

A type library is a language-independent binary file that contains all the information needed to use the component. This includes interface definitions, co-class definitions, structures (UDTs), enumerations, and constants. It is because of type libraries that Visual Basic can implement such great features as Auto List Members (shown in Figure 2.4), Auto Quick Info , and the Object Browser.

Figure 2.4. Auto List Members from type library
figs/vshl.0204.gif

Object Browser is really just a simple type library browser. Although it can provide some very useful information, it does hide a number of things that Microsoft does not want VB programmers to know about. Fortunately, there is a utility called the OLE/COM Object Viewer (usually referred to as OLE View) that will allow us to view the type library generated for Animals.dll without hiding a thing. This utility ships with Visual Studio but is also freely available in the downloads section at http://www.microsoft.com/com.

Example 2.3 shows the type library listing for Animals.dll , which has been generated by OLE View. To view the type library yourself using OLE View, select the View TypeLib option from OLE View's File menu and use the Open dialog to navigate to the Animals.dll file.

Example 2.3. Animals Type Library
 // Generated .IDL file (by the OLE/COM Object Viewer) //  // typelib filename: Animals.dll [   uuid(C6A1FF39-C6B2-11D2-9FCE-00550076E06F),   version(7.0) ] library Animals {     // TLib :          // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}     importlib("STDOLE2.TLB");     // Forward declare all types defined in this typelib     interface _Animal;     interface _Cow;     [       odl,       uuid(74DAE56B-D1C9-11D2-BB7C-444553540000),       version(1.0),       hidden,       dual,       nonextensible,       oleautomation     ]     interface _Animal : IDispatch {         [id(0x60030003)]         HRESULT Kingdom([out, retval] Kingdoms* );         [id(0x60030004)]         HRESULT Name([out, retval] BSTR* );         [id(0x60030005)]         HRESULT Noise([out, retval] BSTR* );     };     [       uuid(C6A1FF3B-C6B2-11D2-9FCE-00550076E06F),       version(1.0),       noncreatable     ]     co-class Animal {         [default] interface _Animal;     };     [       odl,       uuid(74DAE56C-D1C9-11D2-BB7C-444553540000),       version(1.0),       hidden,       dual,       nonextensible,       oleautomation     ]     interface _Cow : IDispatch {     };     [       uuid(C6A1FF3E-C6B2-11D2-9FCE-00550076E06F),       version(1.0)     ]     co-class Cow {         [default] interface _Cow;         interface _Animal;     };     typedef [uuid(74DAE568-D1C9-11D2-BB7C-444553540000), version(1.0)]     enum {         Mammal = 1,         Reptile = 2,         Insect = 3,         Bird = 4,         Fish = 5     } Kingdoms; }; 

Example 2.3 is obviously not Visual Basic, and it isn't C or C++ either, so what is it? Example 2.3 is in a language called IDL , or Interface Definition Language . IDL is compiled using a special compiler, and the result in this case is a type library. This type library has the extension .tlb and can be directly referenced from your VB projects.

2.4.1 Interface Definition Language

Just when you thought you had learned enough languages, along comes Interface Definition Language. IDL is the standard language used to define interfaces. If all the attributes (denoted by square brackets in Example 2.3) were removed from the listing, IDL would pretty much look like standard C.

When you create a component in Visual Basic, the type library is automatically compiled and stored in the component. In other environments, type libraries are usually compiled using the Microsoft IDL (or MIDL) compiler. Unfortunately, MIDL does not ship with Visual Basic; it ships with Visual C++. There is a utility that ships with VB, however, that can be used to generate type libraries. This utility is called MKTYPLIB. The difference between the two is that MKTYPLIB is an ODL ( Object Definition Language ) compiler. ODL is a subset of IDL, so its feature set is limited in comparison to MIDL. Generally, you want to use MIDL for everything, but our circumstances are a bit different. You see, we are going to be redefining system interfaces so that they are VB-friendly. MIDL would complain that several of these interfaces have already been defined and abort the creation of the type library. MKTYPLIB does not care. Therefore, we will use it instead of MIDL.

If you don't know IDL, don't worry. You will still be able to follow along with the book. When all is said and done, you will probably know more about IDL than you ever wanted to know. But I know some of you are probably thinking, "Why can't we just use VB to generate our interfaces?" If only life were that simple. We can't use VB because VB doesn't generate interfaces that look like the interfaces we need. That's the plain truth. Otherwise we would. We'll discuss this later, so save that thought.

Knowing the general layout of a type library will also help sort out some of the confusion. The layout is fairly simple, as Example 2.4 shows. A type library consists of a variable number of blocks. Each block consists of an attribute section denoted by square brackets ( [...] ), followed by the block type ( library , interface , co-class , etc.), and the body, which is surrounded by curly braces ( {...} ). These blocks can be nested, as is the case with an interface definition inside of a library block. Don't worry about the syntax of interface method definitions right now. You will learn about those as you work through each chapter.

Example 2.4. Type Library Structure
 [ / This is the GUID for the library, or LIBID     uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) ] library Name { // This is an interface block     [     // This is the GUID for the interface, or IID         uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)     ]     interface XXXX  : base     {         //Interface methods         HRESULT Foo(...);     } // This is a co-class block [     // This is the GUID for the co-class, or CLSID         uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)     ]     co-class XXXX           {         interface XXXX;     }      } 
2.4.1.1 Attributes

Attributes are keywords used to specify the characteristics of an interface. They describe the data itself and how the data is transmitted. Attributes usually appear in square brackets within an IDL file. Table 2.1 contains a list of attributes, or IDL language keywords, that are found in Example 2.3. (Remember, though, that it does not represent every possible attribute recognized by IDL.) Attributes can be applied to interfaces, the methods of an interface, and even the individual parameters of a method. In fact, most elements of an IDL file can be tagged with attributes.

Table2.1. Interface Attributes in Animal Type Library

Name

Description

default

Indicates that the interface defined inside of a co-class is the default interface. This attribute is for use by macro languages.

dual

Identifies an interface that exposes properties and methods through IDispatch and through the vtable. (See Section 2.6 later in this chapter for more information.)

hidden

Indicates that the item exists but should not be displayed. This attribute is for the benefit of programs like Object Browser.

id

Specifies a DISPID for a member function. (See Section 2.6 later in this chapter for more information.)

nonextensible

This attribute is only valid if the [dual] and [oleautomation] attributes are present. It specifies that the IDispatch implementation includes only the properties and methods listed in the interface description and cannot be extended with additional members at runtime. (See Section 2.6 later in this chapter for more information.) Now, forget about this attribute.

odl

A requirement of MKTYPLIB is that all interfaces have this attribute. It does nothing in and of itself.

oleautomation

Indicates that an interface is compatible with OLE Automation.

uuid

Associates a GUID with an interface.

version

Specifies the version of the type library.

The MIDL Language Reference is part of the Platform SDK (under COM and Active X Object Services) and is available online at http://msdn.microsoft.com/library.

Take note of how settings in VB map to attributes in the type library. For instance, the Instancing property of the Animal class is set to PublicNotCreatable , which causes the attribute [noncreatable] to be added to the Animal co-class. Don't focus too hard on the [oleautomation] and [dual] attributes, though. These attributes will be discussed in detail later on.

2.4.1.2 _ Animal

Let's look at the _Animal interface in Example 2.3 for a moment. In addition to having the [hidden] attribute, an underscore has been added to the interface name, which serves as a signal to Object Browser to keep the interface from being displayed. This is an effort on VB's part to make you believe that an interface and a class are one and the same. It is standard policy to prefix interface names with an I. Had this interface been developed by anything but VB, it most likely would have been called IAnimal .

2.4.1.3 HRESULTs

Consider the definition for the Noise method:

 HRESULT Noise([out, retval] BSTR* ); 

The [out, retval] attribute translates into a function in VB that appears to return a String:

 sNoise = Cow1.Noise 

The actual return value of a method call is an HRESULT . An HRESULT is an unsigned 32-bit value that is used to return error codes or status information back to the caller. VB manages these values for you, which means you can never get direct access to the HRESULT except through the Err object. This is fine if you only need to look at an error code. But this can be a problem in situations where the documentation for the interface states that a method needs to return a specific HRESULT . VB does not give us the power to return specific HRESULT s from an implemented method. Also, using the Err.Raise method to generate a specific error condition will not achieve the same result as returning an HRESULT .

Unless an error occurs, the actual return value is 0; otherwise, it is a number in the form -214 xxxxxxx . Although VB interprets the value to be a negative number, the number is not actually negative; VB does not handle unsigned datatypes (other than Byte). Because of this, large numbers (that is, integer values whose high order bit of their highest order byte is set on) appear to be negative.

As you can see, VB returns HRESULT s through the Err object in decimal format, but the rest of the world uses hexadecimal. So, if you convert the HRESULT codes to hex using the VBA Hex function, you should be able to locate most of the standard return codes in winerror.h . This file also contains the specific bit mapping for an HRESULT and is a very useful resource when debugging COM servers. Unfortunately, this file is only available with Visual C++.

only for RuBoard - do not distribute or recompile


Visual Basic Shell Programming
Visual Basic Shell Programming
ISBN: B00007FY99
EAN: N/A
Year: 2000
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net