Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
|
Delphi 5 CORBA Server
I start by developing a CORBA Server which encapsulates some features of the CodeSite debugger from Raize Software.
CodeSite is my debugger of choice, for both Delphi and C++Builder, and offers a CodeSite object (to link in with my Delphi and C++Builder applications) as well as a CodeSite viewer.
The CodeSite object contains several methods to send information (strings, integers, etc.) to the viewer, which displays the messages in a useful way using indenting, timestamps, etc.
For more information on CodeSite, check out the Raize Software website.
Start Delphi 5 with a new application, and add a CORBA Object to it (from the Multitier tab of the Object Repository):
When you select the CORBA Object icon and click on the OK-button, the "CORBA Object Wizard" is displayed.
Here, we can specify what kind of CORBA Server we need.
Apart from the name, which is set to CodeSite, we must specify a value for Instancing and the Threading Model.
For "instancing", we can select Instance-per-client, which means that for each client connection, a new instance of the CORBA object is created.
The alternative is a shared-instance, which means that a single CORBA object is shared between each client.
In this case, I've selected the Instance-per-client model.
The threading model can be single-threaded or multi-threaded.
In this case, I want to avoid all threading issues, so I've selected the single-threaded model:
After you've set all these options, click on OK to generate your CORBA object. The most important line in the source code (see below) can be found inside the initialization section, where the TCorbaObjectFactory.Create is called to create the CodeSiteFactory. Note that this is the place that specifies our choices for iMultiInstance (i.e. instance-per-client instead of shared-instance)and tmSingleThread. This also means that we can change these settings at a later time, for example change iMultiInstance to iSingleInstance to change our CORBA server to an instance-per-client object.
unit CSServer; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, ComObj, StdVcl, CorbaObj, CSCServer_TLB; type TCodeSite = class(TCorbaImplementation, ICodeSite) private { Private declarations } public { Public declarations } end; implementation uses CorbInit; initialization TCorbaObjectFactory.Create('CodeSiteFactory', 'CodeSite', 'IDL:CSCServer/CodeSiteFactory:1.0', ICodeSite, TCodeSite, iMultiInstance, tmSingleThread); end.Interfaces
Make sure to click on the "Refresh Implementation" button so the three methods are also reflected in the CSServer unit itself. At this time, we can export the IDL definition (click on the arrow-button on the upper-right of the Type Library Editor, and export the type library as CORBA IDL). The resulting IDL file can be seen below:
module CSCServer { interface ICodeSite { void SendMsg(in wstring Str); void EnterMethod(in wstring Str); void ExitMethod(in wstring Str); }; interface CodeSiteFactory { ICodeSite CreateInstance(in string InstanceName); }; };Once we have this CORBA IDL file, we can send it to the other side (in this case I've e-mailed it to Hubert to let him create a JBuilder 3.5 on Linux CORBA Client for it).
Server Skeleton
While Hubert is building his CORBA client based on our IDL file, we can go back to the CSServer unit to implement our server skeletons.
For this, we actually need to use the CodeSite object itself, of course.
Adding the RzCsIntf unit to the uses clause of our implementation section is enough, as this gives us access to the global CodeSite object.
Each of the three new methods of our CORBA server only need to call the CodeSite counterpart, passing the single WideString argument.
CodeSite itself will take care of the rest.
unit CSServer; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, ComObj, StdVcl, CorbaObj, CSCServer_TLB; type TCodeSite = class(TCorbaImplementation, ICodeSite) protected procedure EnterMethod(const Str: WideString); safecall; procedure ExitMethod(const Str: WideString); safecall; procedure SendMsg(const Str: WideString); safecall; end; implementation uses CorbInit, RzCsIntf; procedure TCodeSite.EnterMethod(const Str: WideString); begin CodeSite.EnterMethod(Str) end; procedure TCodeSite.ExitMethod(const Str: WideString); begin CodeSite.ExitMethod(Str) end; procedure TCodeSite.SendMsg(const Str: WideString); begin CodeSite.SendMsg(Str) end; initialization TCorbaObjectFactory.Create('CodeSiteFactory', 'CodeSite', 'IDL:CSCServer/CodeSiteFactory:1.0', ICodeSite, TCodeSite, iMultiInstance, tmSingleThread); end.Each CORBA client that connects to this CodeSite CORBA server can use the EnterMethod, ExitMethod and SendMsg methods to send a debug message from the CORBA client to the CORBA server which will then display it inside the CodeSite Viewer that's running on the same machine. The output of Mr.Haki's JBuilder 3.5 on Linux CORBA Client is as follows:
The only problem, once we've got things working, is the fact that multiple CORBA clients can connect to our CORBA server at the same time. And while this doesn't mean we get threading issues, it does mean that we can't distinguish between messages from one client and another inside the CodeSite viewer: each message will be sent by... the CORBA server (since that's the application that's sending messages to CodeSite, not the CORBA client). A workaround would be to add the name of each CORBA client as first string to the three Str arguments. This can be done by the clients (not recommended) or by the Server automatically, provided we give each client a way to identify itself using an addition ID argument. We haven't implemented this feature in this article, but I'm sure you get the idea. For now, the result is that using a set of CORBA client stubs, we can write JBuilder applications on Linux and debug them on another machine running WinNT using CodeSite (provided the CodeSite CORBA server is running as well).