Saturday, November 2, 2024

Writing COM Components in Perl Part 1

When you strip away all the layers of marketing hype and industry jargon, Microsoft’s Component Object Model (COM) is simply a technology that allows you to create an object in the language of your choice, and to make the functionality of that object available to any other object, or any other application, regardless of the language that the other object or application is written in.

Yikes! Quite a mouthful. Maybe it would be useful to come at this by way of an example.

Suppose that we are required to write three applications. These three applications will be identical in terms of functionality. Specifically, they will gather data entered on a form and email it.

However, though all three applications will do the same thing, in our hypothetical example, each application will be programmed in a different programming language. Specifically, we will write one form processor in C++, one in Java, and one in Perl.

In writing these applications, it is likely that we will define several objects.

For example, there will be an object representing the form and there will be an object in charge of connecting to a mail server and delivering the email message.

In order for each program to work, each of these objects, will have to be defined in each of the three languages. Thus, you will have one mailer in C++, one mailer in Java, and one mailer in Perl.

As you might imagine, this is quite inefficient. The algorithm involved in connecting to a mail server and delivering the email message is not really language specific. So why should we have to write it three times?

Well traditionally, the reason is because C++ applications can’t really speak to Java objects. Java objects can’t speak to Perl objects and Perl objects can’t speak to Visual Basic objects. Traditionally, objects are like cliques in high school! Groups never mingle.

In the COM universe however, anything can talk to anything else. Thus, in the COM universe, you do not write three mailer objects. Instead, you write one special mailer object that can be used by any application in any language. It is an object that conforms to the COM specification. It is a COM object.

As we said, this COM object may be written in any language you like (C++, Java, Perl, VB, etc) but because it conforms to the COM specification, it will be available as a resource to any COM-aware applications regardless of what language that application is written in. Thus, you could write a single mailer (as a COM object) in Perl and make that mailer available to all your programs, whether those programs are written in Perl, Java, VB, or C++.

What are COM objects?

So how does COM allow you to perform this magic?

The key to writing COM components in Perl is Activestate’s Perl Development Kit [ the PDK – currently in release 1.2.4 ] . The reason you need a third party tool in order to turn your Perl objects into COM components will become apparent as you read further.
When you break them down to their essences, all objects do the same basic things no matter what languages they are written in. Specifically, all objects have methods and properties that define how they work internally.

Further, all objects expose a set of “public” methods that allow objects in the outside world to interact with them.

Finally, it is often the case that methods accept a set of incoming parameters that modify the behavior of the method, and return some type of output to the caller of the method.

Usually, every programming language will implement these basic characteristics, but will do so in slightly different ways. For example, consider the same add() method defined first in Java and then in Perl:

&nbsp public int add(int a, int b) {
&nbsp &nbsp &nbsp return a+b;
}

sub add {
&nbsp &nbsp &nbsp my $a = shift;
&nbsp &nbsp &nbsp my $b = shift;
&nbsp &nbsp &nbsp return $a + $b;
}

Quite different, eh? That’s why it is so hard for languages to interact.

The beauty of COM is that it defines a language-independent specification that abstracts out these basic object properties.

COM is a protocol that defines a standard way for objects to speak to one another, regardless of the specific way in which they actually implement methods and properties.

More specifically, COM is a specification that defines how to call methods on objects.

The IDL

Ask a seasoned COM developer what concept is at the heart of COM’s egalitarian society, and the response will probably be something to the effect of “COM depends on interfaces”.
An interface provides a detailed contract that specifies exactly how the objects should be allowed to communicate.

So why go through the trouble of writing a contract for every object in your program?!?

Well, the interface provides a protective layer that sits between objects.

As such, an interface assures both parties that no matter how each object changes internally, that the two objects will always be able to communicate because they will always implement the interface in exactly the same way.

In other words, implementation is entirely opaque to those who use the object – and this is exactly the way that it should be. Not only do I now want to spend time understanding how object X implemented its functionality, but if object X changes that implementation, it should not break objects that had depended on it.

Let’s look at this by example. Consider what happens if you press the accelerator in a car – it speeds up. The wonder of a car is that you don’t have to know anything whatsoever about the functioning of the engine in order to accelerate. You just depress the gas pedal and go. And this is the same for any car you use!

Further, how you use the car is independent of how the engine changes, you always go faster by doing the same thing – pressing the accelerator. The engine’s implementation, whether it is a 6 litre or a 4 litre, whether it uses the newest new fangled electro-E-Virtual-Cyber carburettor or not, is entirely internal. You interact with nothing except its interface. In fact you don’t need to know or even care about how the engine works!

To abstract away implementation, COM defines an interface definition language [IDL]. This IDL is used to specify the abstract characteristics of methods (such as they take parameters and can return results) such that the concept of methods is separated from the implementation of methods.

If you are a Java programmer, think of COM as being roughly similar to the way that Javabeans work. When you write a Javabean and drop it into a Bean-aware development environment, the environment only knows what your object is capable of because you have written your object so as to comply with the Javabean pseudo API.

The interface definition language wraps your object and does nothing else except describe your object in terms of the methods and properties that it exposes to the world at large. It is a contract that your object makes with the COM runtime about what it is capable of. The implementation of the functionality is of no importance to COM – it is your responsibility as a developer to provide it.

As a result, COM does not understand anything other than an IDL. Thus, if you write an object and you want to package it as a COM component, you [or your development environment] must define the IDL that describes your object in terms of COM.

Once the IDL is validly defined, you can plop your object into any COM-aware environment and other objects can begin to use it.

COM objects run within a COM runtime. The runtime is responsible for all the message passing between COM components and applications, or between COM components and each other. Because your object is defined in terms of a valid IDL, the COM run time will have all it needs to do the message passing.

Objects actually define multiple interfaces depending on their complexity. But this should not be hard to understand. Most objects can do many different things. Consider the human being in terms of a programming object.

Humans are very flexible in terms of their capabilities. They can, amongst other things, move as well as sense their surroundings. Within the first category, the object may have methods such as walk, run and crawl. Within the second category, senses, we may choose to include such things as hearing, seeing, tasting and touching.

While it is therefore true to say that the entire interface of the [ simplified ] human object are walking, running, crawling, hearing, seeing, tasting, and touching, COM developers tend instead to describe their objects in terms of functionally related methods instead, although this division is not mandatory.

The human COM object, therefore, would be more likely described as implementing 2 interfaces, the movement interface and the sensing interface. Each interface would then contain a list of its related functions. Of course it is the ubiquitous IDL that is going to provide the interface descriptions.

Of course, although any object can have multiple interfaces, they must have at least one.

Each and every COM object that you write implements the IUnknown interface by default (you do not need to do anything to ensure this). It is the IUnknown interface that provides the absolute minimum functionality that every COM object is going to require, regardless of the methods/properties that you provide via the custom interfaces that you implement. The methods of the IUnknown interface deal with such things as reference counting for the object, so as to ensure it is garbage collected at the appropriate time. It is also via the IUnknown interface that the object can be queried regarding the other interfaces that it implements, and therefore about its capabilities.

COM objects that are going to be used by languages without strict data typing [ such as VBScript, Perl, and Javascript ], also implement the IDispatch interface.

A detailed discussion of the functionality and internals of the IUnknown and IDispatch interfaces is really beyond the scope of this article, as it would lead very quickly into the detailed internals of COM. But you should at least get familiar with the names.

COM components run in the context of Microsoft’s COM runtime. It is the COM runtime that is responsible, transparently, for making sure that method calls reach the proper objects and methods within a COM object, and that the results of these calls are returned to the calling application as expected.

The objects that comprise the COM runtime, and do all this work behind the scenes are packaged in a number of Dynamic Link Libraries [DLLs], that are installed on the system.

In the context of Perl, the PDK is this development environment that is going to take your Perl components, and describe them in a COM compliant manner – in effect, wrapping your Perl object in a COM IDL wrapper.

So where do you obtain the PDK? How do you install the PDK? How do you use the PDK? All these questions will be answered in good time. But first, we have not completed our whistle stop tour of COM.

How does the IDL describe my object?

The IDL description of your object operates in terms of Interface definitions.

If an object states in the IDL that it implements a particular interface then it is advertising the fact that it implements all the methods within that interface.

For example, consider a SeniorManager object. This object might implement the following methods

  • hirePeople()
  • firePeople()
  • startProject()
  • endProject()
  • The IDL description of this object could state that this object implemented 2 custom interfaces, the changeHeadCount interface [ comprising methods 1 and 2 ] and the manageProject interface [ comprising methods 3 and 4 ].

    In fact, given the interface naming conventions that COM uses, these 2 interfaces would probably more likely be called IchangeHeadCount and ImanageProject, with the leading “I” standing, funnily enough, for “Interface”.

    The topic of COM interfaces is substantially more detailed than has been laid out above, but a Perl developers writing COM components does not need to have more than a very basic knowledge of the significance of interfaces in COM. This is for 2 reasons

  • COM objects written in Perl have their IDL description generated by the PDK. This means that you do not have to worry about writing any of your own interface definition for your object, as you might have to were you implementing it in C++.
  • Because the PDK generates the IDL description of the methods of your object, you have no way of defining any custom interfaces that the COM object implements. Consider the IchangeHeadCount and ImanageProject interfaces mentioned above. If you wanted to state that your object implemented these, you would have to have some way of writing the IDL to say as much. The PDK, however, does this all for you. All Perl COM components implement only one interface, called “I[perl class name]” – so for example the SeniorManager object would be stated to implement ISeniorManager, which would comprise, all together, the 4 methods listed above. It is the PDK, therefore, that is responsible for defining the custom interface that your class implements.
  • This is nothing more than a very cursory introduction to a topic that lies at the very heart of COM – interface based programming. For those of you who wish to investigate the subject above and beyond the scope of this article, topics such as the IDispatch and IUnknown default COM interfaces, and early and late binding [ amongst many other things ] await you.

    *Originally published at Extropia.com

    Eric Tachibana (also known as Selena Sol) has been at the forefront of
    the web applications development industry since its inception. Author
    of 7 best-selling technology books with topics ranging from Perl, Java,
    XML, and Banking Software Development, to Microsoft AFC, Security, and
    E-Commerce, Tachibana is widely known as a seminal personality in the
    web-programming community. His Open Source contributions in particular have earned him recognition
    from several prestigious award bodies and he is in high demand as a
    speaker on web technology, security, and technopreneurship regionally.

    Related Articles

    LEAVE A REPLY

    Please enter your comment!
    Please enter your name here

    Latest Articles