The RIDL Format COM Servers

PM Milestone Project Management Templates

PM Milestone Business Templates

Get Instant Access

To see what this new RIDL format is all about, let's convert an existing COM project by opening it in Delphi 2009. As an example, I've taken the SimpleServer COM example of Mastering Delphi 2005 and converted it to Delphi 2009. Beside the standard project file format conversion, Delphi warned me of the type library migration:

Converting '...\O8\SimpleServer\SimpleServer.tlb' to .ridl format Reading 'SimpleServer.tlb' Writing 'SimpleServer.ridl' Adding 'SimpleServer.ridl' Removing 'SimpleServer.tlb'

If we look at the project files in the Project Manager, we can see the new RIDL file:

Simple Server.dproj - Project Manager | s

ft ti -1


ProjectGroup3 S-[jfp SimpleServer.dll

[+}•• Build Configurations j--^ Numlmpl.pas SimpleServer.ridl SimpleServer_TLB.pas

< 1 -■»— 1 ►

SimpleS... 1 if?Model Vi... | J^DataEx...

If we look to the project file source code, instead, we can still see the classic reference to the TLB resource file. The type library, in fact, is still included in the executable, after it is compiled from the RIDL file.

How the TLB gets converted and how the RIDL file is generated mostly depends on some Tools Options for the type library. These options are quite different than in the past. In particular, as this is an in-process server, to keep the code compatible (and easier from the Delphi perspective) we need to enable safecall130 mapping for any COM interface, using the Environment Options settings below:

Delphi 2010 Environment Options

As the default is to have safecall mappings only for dual interfaces, you'll generally have to change these settings, and need to do so before opening the project (or reopen the project after changing the settings, as the Delphi

130 Using the safecall convention all COM calls are mapped, so the error checking done in terms of HRESULT in the system are remapped to exceptions on the Delphi side. Basically each function or procedure becomes a function with an HRESULT return value, as requested by COM dual interfaces, and an extra out parameter is possibly added for the actual return value. On the server side Delphi wraps the code in a try except block which will eventually trap an exception and return an error code. On the client side, an error code in a call will force Delphi to raise the corresponding exception.

IDE will suggest to you, but beware you might have to open the type library editor a couple of times before the code is generated the way you asked).

If you can reopen the type library in the IDE, you'll see a type library editor very similar to the past:

  • Welcome Page lifD SlmoleServer -A- SlmpleServer.rldl ^
  • Welcome Page lifD SlmoleServer -A- SlmpleServer.rldl ^
Delphi Ridl

Refresh the type library editor implementation (using the Refresh button of the toolbar of this pane) to generate or update the RIDL file.

For the SimpleServer example, which I've upgraded from an older version of Delphi, I got the following RIDL code, which imports a standard Delphi type library, defines the INumberProp interface, with a property and a method, and defines the NumberProp coclass (construction class) for the server object implementing the interface:

library SimpleServer {

import1ib("stdo1e2.t1b"); [

uuid(4D24B32A-DE61-4EBE-AE53-6DF2D3DC80DA), version(1.0), he1pstring( "Interface for NumberProp Object'), oleautomation

interface INumberProp: IUnknown {

[propget, id(0x00000065)]

HRESULT _stdca11 Va1ue([out, retval] long* New); [propput, i d(0x00000065)] HRESULT _stdca11 Va1ue([in] long New); [id(0x00000066)]

HRESULT _stdca11 Increase(void);

uuid(BDC9A273-A973-4DB4-ADE7-8F0A49004D29), version(1.0), helpstri ng("NumberProp")

coclass NumberProp {

[default] interface INumberProp;

This interface is independent from the safecall mapping decisions, which are reflected only in the corresponding Delphi code. You can see a first interface, based on IUnknown, with a Value property defined by a getter and a setter and an Increase method. In terms of the corresponding Delphi interface, the code is generated as follows (and remains very similar to the past) and placed in a SimpleServer_TLB.pas unit:


INumberProp = interface(IUnknown)

[ '{4D24B32A-DE61-4EBE-AE53-6DF2D3DC80DA}'] function Get_Value: Integer; safecall; procedure Set_Value(New: Integer); safecall; procedure Increase; safecall; property Value: Integer read Get_Value write Set_Value;

CoNumberProp = class class function Create: INumberProp; class function CreateRemote(

const MachineName: string): INumberProp;

Having forced the generation of safecall mappings, I didn't have to touch the original source code of the implementation class: type

TNumberProp = class(TTypedComObject, INumberProp) private fValue: Integer; protected procedure Increase; safecall; function Get_Value: Integer; safecall; procedure Set_Value(New: Integer); safecall; publ ic procedure Initialize; override; destructor Destroy; override; end ;

When everything works fine, porting existing code will be smooth. What might happen, though, is that if you set up the wrong calling convention (and the IDE picks the wrong calling convention despite your settings), you'll see both the interface and the implementation class having extra methods with the stdcall convention and the HRESULT return value directly visible. If this happens, the extra methods are added to the class, aliased as the class already has similarly names methods, and this can really mess up the code, preventing it from compiling and making it far from trivial to restore it (unless, of course, you got back to the previous version in the file history or simply avoid saving the modified file).

Was this article helpful?

0 0
Project Management Made Easy

Project Management Made Easy

What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.

Get My Free Ebook


  • iole
    How to modify the ridl in delphi?
    9 years ago

Post a comment