Understanding Life without IDL

 < Free Open Study > 



Up until this point in our journey, we have defined our COM interfaces in C++ using the class, interface, and struct keywords. We can ensure these interfaces expand correctly on various platforms using a small handful of COM macros (STDMETHOD, STDMETHOD_, STDMETHODIMP, and STDMETHODIMP_ being the most common). Sadly, despite the usefulness of these macros, we have still written COM interfaces that can only be implemented and accessed using the C++ language.

COM is a very inclusive club. A well-defined interface should be able to be implemented by, and accessed from, any COM-enlightened language. Currently, Visual Basic, C, or Java developers cannot create our coclasses or access any of our custom interfaces. For example, a VB developer cannot declare an IDraw variable, as IDraw was defined in C++ syntax. If a language can't create a variable of the correct type, it has no way to store the logical return value of QueryInterface(). The moral of the story is that interfaces defined in a given language are usable only from that language. Obviously this is a problem for a language-independent specification such as COM.

We have another even more insidious problem occurring here. Each COM-enabled language allows developers to assign GUIDs in language- and environment-specific ways. For example, if we wish to assign an IID in C++, we first create the interface definitions and then manually associate a GUID using the DEFINE_GUID macro (or another format provided by guidgen.exe).

VB, on the other hand, automatically associates a GUID to custom interfaces at compile time, without developer participation. Furthermore, a VB developer has no way to change the GUID generated by VB. To illustrate how this behavior can spell trouble, consider again the IShapeEdit interface defined in C++, now with an associated GUID constant:

// {442F32E2-E7EE-11d2-B8D2-0020781238D4} DEFINE_GUID(IID_IShapeEdit, 0x442f32e2, 0xe7ee, 0x11d2, 0xb8, 0xd2, 0x0, 0x20, 0x78, 0x12, 0x38, 0xd4); DECLARE_INTERFACE_(IShapeEdit, IUnknown) {      STDMETHOD(Fill) (FILLTYPE fType) PURE;      STDMETHOD(Inverse) () PURE;      STDMETHOD(Stretch) (int factor) PURE; };

A savvy VB developer can create a COM interface named IShapeEdit as well, as shown in Figure 4-1 (VB supplies the necessary IUnknown methods behind the scenes):

click to expand
Figure 4-1: A VB definition of the custom IShapeEdit interface.

If we examine the GUID generated by VB for this definition of IShapeEdit (using the OLE/COM Object Viewer, which is mentioned later), we might find an assigned IID of {91D5CC38-E644-11D2-B8D1-0020781238D4}. If you are thinking, "I thought IShapeEdit was already assigned an IID of {442F32E2-E7EE-11d2-B8D2-0020781238D4}," you are beginning to see the problem.

If a VB developer (whom we'll call Frank) "just happened" to create a new interface named IShapeEdit without any knowledge of our existing C++ interface definition, all would be fine as far as COM is concerned. The separate GUIDs ensure a unique tag for each definition. If, however, Frank thought, "Hey! I want my VB object to support Gerta's IShapeEdit interface, I'll rewrite it in VB," then we have a huge problem. Frank did not want to create a new interface at all, but wanted to reuse an existing interface written in C++. If Frank and Gerta were members of the same development team, we have assigned two GUIDs to the same behavior. Imagine the problems injected into the COM mainstream if a C++ developer created a new coclass deriving from IUnknown, and in the process, assigned a new GUID to the IID_IUnknown constant! The same potential nightmare exists here.

What we need is a higher level metalanguage that we may use to define our COM items once and for all, and let developers use their language of choice to implement and work with the definitions (interfaces, types, coclasses, and so on). This metalanguage is Microsoft's Interface Definition Language, or simply MIDL.

The Origins of MIDL

Microsoft's Interface Definition Language (MIDL) is an extension of an older existing IDL standard. The IDL used in modern-day COM development is based off of the "Open Software Foundation Distributed Computing Environment Remote Procedure Call Interface Definition Language," which gives us one of the longer acronyms out there in the universe: OSF DCE RPC IDL. Let's just call this DCE IDL for short.

DCE IDL allows software developers to write descriptions of remote procedure calls (RPCs). It is important to note that DCE IDL had no support for object-based definitions. All DCE IDL code revolved around the tried and true structured programming (SP) paradigm, and the output of DCE IDL definitions was tailored to C and C++ language mappings (that would be "C++ as a better C," not OOP-based C++).

Microsoft IDL extends DCE IDL to support numerous items such as COM interfaces, interface inheritance, coclass definitions, and type information by introducing a handful of new keywords. Under the hood, MIDL still supports DCE IDL, as MIDL is an extension of DCE IDL's functionality.

Note 

From here on out, when mentioning IDL, assume we are referring to Microsoft's Interface Definition Language (MIDL) unless otherwise noted.

A Working Definition of IDL

IDL is a C-like language with the additional notion of attributes. Attributes are blocks of IDL keywords that remove any possibility of ambiguity from a COM definition. For example, there are attributes that assign GUIDs to COM interfaces, attributes that specify the direction of method parameters (necessary for effective marshaling), and attributes that specify the "default interface" of a coclass. We will see each of these IDL aspects in turn.

Real COM developers write IDL definitions to describe the full functionality of their COM server and send the *.idl file into the MIDL compiler (midl.exe). Midl.exe will generate a number of output files that may be consumed by COM object builders, as well as object users. These files are the keys to COM's language independence and location transparency.

Note 

You may have heard of the Object Definition Language, or ODL. This definition language is an older incarnation of MIDL, designed specifically to create type libraries for OLE automation servers using the MkTypLib.exe utility. MIDL 2.0 did not support type library generation, but generated stub and proxy code to marshal COM interfaces between apartment, machine, and process boundaries. Nowadays with MIDL 3.0, anything you could describe in ODL may be described in IDL (including type libraries). Unless you have inherited some legacy ODL definitions, you can safely ignore the older ODL syntax and stick to modern-day IDL.

What Does COM IDL Bring to the Table?

IDL is only a definition language. The syntax of IDL is modeled after C; however, you will find no support for looping constructs (for loops, while loops, and the like) or decision statements (if/else, switch, and so on). You will never (and could never) build an executable program such as MS Word using IDL code, and cannot implement coclasses with IDL either! So what exactly can you do with IDL? To understand the answer to this question, recall some of the problems we had without it:

  • COM items defined in a given language are bound to that language.

  • Many COM language mappings assign GUIDs automatically, which could result in duplication of interface behaviors (which may or may not be problematic).

When you describe your COM servers using IDL, we ensure the following:

  • GUIDs are established once and for all for each COM item.

  • We can remove any ambiguity from our definitions using IDL attributes.

  • We provide a language-neutral way to allow COM-enabled languages to implement our interfaces and program against our coclasses.

  • We automatically receive stub and proxy code to remotely access COM interfaces (this point is the subject of the next chapter, so put this on the back burner until then).



 < Free Open Study > 



Developer's Workshop to COM and ATL 3.0
Developers Workshop to COM and ATL 3.0
ISBN: 1556227043
EAN: 2147483647
Year: 2000
Pages: 171

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