Chapter 45
Creating a simple COM object

Delphi provides wizards to help you create various COM objects. This chapter provides an overview of how to create a simple, lightweight COM object, such as a shell extension, in the Delphi environment. To create Automation client and server objects, see "Creating an Automation controller," and "Creating an Automation server." To create an ActiveX control, see "Creating an ActiveX control." To create an Active Server Page, see "Creating an Active Server Page."

This chapter is not intended to provide complete details of writing COM applications. For that information, refer to your Microsoft Developer's Network (MSDN) documentation. The Microsoft Web site also provides current information on this topic.

Overview of creating a COM object

Use the COM object wizard to create a simple, lightweight COM object, for example, a shell extension. A COM object can be implemented as either an in-process server, out-of-process server, or remote server.

The COM object wizard performs the following tasks:

The process of creating a COM object involves these steps:

  1. Design the COM object.
  2. Use the COM object wizard to create a COM object.
  3. Register the COM object.
  4. Test the COM object.

Designing a COM object

When designing the COM object, you need to decide what COM interfaces you want to implement. The wizard supplies the IUnknown interface. If you want to implement any other COM interfaces, see the MSDN documentation.

You must decide whether the COM object is an in-process server, out-of-process server, or remote server. For in-process servers and for out-of-process and remote servers using a type library, COM marshals the data for you. Otherwise, you must consider how to marshal the data to out-of-process servers.

For information on server types, see"In-process, out-of-process, and remote servers".

Creating a COM object with the COM object wizard

Before you create a COM object, create or open the project for an application containing functionality that you want to implement. The project can be either an application or ActiveX library, depending on your needs.

To bring up the COM object wizard,

  1. Choose File|New to open the New Items dialog box.
  2. Select the tab labeled, ActiveX.
  3. Double-click the COM object icon.

In the wizard, specify the following:

ClassName

Specify the name for the object that you want to implement.

Instancing

Specify an instancing mode to indicate how your COM object is launched. See "COM object instancing types" for details.

Note: When your COM object is used only as an in-process server, instancing is ignored.

Threading model

Choose the threading model to indicate how client applications can call your COM object's interface. For details, see "Choosing a threading model".

Note: The threading model you choose determines how the object is registered. You must make sure that your object implementation adheres to the model selected.

Implemented interfaces

Specify the names of the COM interfaces that you want this COM object to implement.

Description

Enter a description of the COM object you are creating.

Include Type Library

Check this box to generate a type library for this object. A type library contains type information that allows you to expose any object interface and its methods and properties to client applications. Checking this box automatically causes Mark Interface OleAutomation to be checked.

Mark interface OleAutomation

Check this box to enable the marshaling code that gets generated when you create a type library. COM knows how to marshal all the Automation-compatible types in the type library and can set up the proxies and stubs for you so that you can pass parameters to out-of-process (.EXE) servers. For more information, see "The marshaling mechanism".

COM object instancing types

Note: Instancing is ignored when your COM object is used only as an in-process server.

When your COM application creates a new COM object, it can have any of the following instancing types:

Instancing

Meaning

Internal

The object can only be created internally. An external application cannot create an instance of the object directly. For example, a word processor application may have a document object that can only be created by calling a method of the application that can create the document object.

Single Instance

Allows only a single COM interface for each executable (application), so creating multiple instances results in creating multiple applications. Single instance specifies that once an application has connected to the object, it is removed from public view so that no other applications can connect to it. This option is commonly used for multiple document interface (MDI) applications. When a client requests services from a single instance object, all requests are handled by the same server. For example, any time a user requests to open a new document in a word processor application, typically the new document opens in the same application process.

Multiple Instance

Specifies that multiple applications can connect to the object. Any time a client requests service, a separate instance of the server gets invoked. (That is, there can be multiple instances in a single executable.) Any time a user attempts to open the Windows Explorer, a separate Explorer is created.

Choosing a threading model

When creating an object from the wizard, you select a threading model that your object agrees to support. By adding thread support to your COM object, you can improve its performance.

Table 45.1 lists the different threading models you can specify.

Table 45.1   Threading models for COM objects

Threading model

Description

Implementation pros and cons

Single

No thread support. Client requests are serialized by the calling mechanism.

Clients are handled one at a time so no threading support is needed.

No performance benefit.

Apartment (or Single-threaded apartment)

Clients can call an object's methods only from the thread on which the object was created. Different objects from the same server can be called on different threads, but each object is called only from that one thread.

Instance data is safe, global data must be protected using critical sections or some other form of serialization.

The thread's local variables are reliable across multiple calls.

Some performance benefits.

Objects are easy to write, but clients can be tricky.

Primarily used for controls for Web browsers.

Free (also called multi-threaded apartment)

Clients can call any object's methods from any thread at any time. Objects can handle any number of threads at any time.

Objects must protect all instance and global data using critical sections or some other form of serialization.

Thread local variables are not reliable across multiple calls.

Clients are easy to write, but objects are harder to write.

Primarily used for distributed DCOM environments.

Both

Objects can support clients that use either apartment or free threading models.

Maximum performance and flexibility.

Supports both threading models when clients may be either using single-threaded or free for improved performance.

Both the client and server sides of the application tell COM the rules it intends to follow for using threads when it initializes COM. COM compares the threading rules that each party has agreed to support. If both parties support the same rules, COM sets up a direct connection between the two and trusts that the parties follow the rules. If the two parties advertise different rules, COM sets up marshaling between the two parties so that each sees only the threading rules that it says it knows how to handle. Of course, marshaling affects performance somewhat, but it allows parties with different threading models to work together.

Note: The threading model you choose in the wizard determines how the object is advertised in the registry. You must make sure that your object implementation adheres to the threading model you have chosen.

The threading model is valid for in-process servers only. Setting the threading model in the wizard sets the threading model key in the CLSID registry entry, InProcessServer32.

Out-of-process servers are registered as EXE and it is up to you to implement the threading model yourself. If the EXE contains a free threaded server, Delphi will initialize COM for free threading, which means that it can provide the expected support for any free-threaded or apartment-threaded objects contained in the EXE. To manually override threading behavior in EXEs, see the CoInitFlags variable in online Help.

Note: Local variables are always safe, regardless of the threading model. This is because local variables are stored on the stack and each thread has its own stack.

Writing an object that supports the free threading model

Use the free threading model rather than apartment threading whenever the object needs to be accessed from more than one thread. A common example is a client application connected to an object on a remote machine. When the remote client calls a method on that object, the server receives the call on a thread from the thread pool on the server machine. This receiving thread makes the call locally to the actual object; and, because the object supports the free threading model, the thread can make a direct call into the object.

If the object supported the apartment threading model instead, the call would have to be transferred to the thread on which the object was created, and the result would have to be transferred back into the receiving thread before returning to the client. This approach requires extra marshaling.

To support free threading, you must consider how instance data can be accessed for each method. If the method is writing to instance data, you must use critical sections or some other form of serialization, to protect the instance data. Likely, the overhead of serializing critical calls is less than executing COM's marshaling code.

Note that if the instance data is read-only, serialization is not needed.

Writing an object that supports the apartment threading model

To implement the (single-threaded) apartment threading model, you must follow a few rules;

The single-threaded apartment model is the middle ground between providing no threading support and full, multi-threading support of the free threading model. A server committing to the apartment model promises that the server has serialized access to all of its global data (such as its object count). This is because different objects may try to access the global data from different threads. However, the object's instance data is safe because the methods are always called on the same thread.

Typically, controls for use in Web browsers use the apartment threading model because browser applications always initialize their threads as apartment.

For general information on threads, see "Writing multi-threaded applications."

Registering a COM object

After you have created your COM object, you must register it so that other applications can find and use it.

Note: Before you remove a COM object from your system, you should unregister it.

To register a COM object,

To unregister a COM object,

As an alternative, you can use the tregsvr command from the command line or run the regsvr32.exe from the operating system.

Testing a COM object

Testing your COM object depends on the COM object you have designed. Once you have created the COM object, test it by using the interfaces you implemented to access the methods of the interfaces.

To test and debug a COM object,

  1. Turn on debugging information using the Compiler tab on the Project|Options dialog box, if necessary. Also, turn on Integrated Debugging in the Tools|Debugger Options dialog.
  2. For an in-process server, choose Run|Parameters.
  3. In the Host Application box, type the name of the client application which will be requesting the service of this COM object, and choose OK.
  4. Choose Run|Run.
  5. Set breakpoints in the COM object.
  6. Use the client application to interact with the COM object.

The COM object pauses when the breakpoints are reached.