Logged in as Guest
Open Source Visual RAD



Home >
Getting Started >
GNAVI FAQ >
The GNAVI Project >
GNAVI Extras >
Join >
Latest Additions >
Press Releases >
Links >
Contact >
About >
Login >

Back
GNATCOM - Overview
RAD Active X/COM/DCOM Framework

<p>GNATCOM Overview

GNATCOM Overview

Ada 95 COM/DCOM/COM+ Development Framework and Tools

October, 2004

David Botton


(C) Copyright 1999-2004 David Botton

This document is distributed under the terms of the GNU General Public License. You can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

.

Introduction     Introduction to GNATCOM
Framework     GNATCOM Framework Overview
Tools     GNATCOM Tools Overview
Samples     Sample GNATCOM applications
Tutorial     GNATCOM Tutorial
Support     Support for GNATCOM

Introduction to GNATCOM

GNATCOM comprises a framework covering binding and creation of all COM (Component Object Model) technology based objects and four powerful tools, MakeGUID, COMScope, BindCOM, and CreateCOM.

Thanks to GNATCOM the incredible wealth of technologies on the Windows 9X, NT, 2000, XP platforms become immediately available to Ada 95 applications. To name just a few, XML parsers, full control over Internet Explorer including integration and binding to its DHTML model, Microsoft Message Queuing, integration with Visual Basic Forms, OLEDB and ADO (Active Data Objects), MAPI, and more. GNATCOM also makes it easily possible for the many applications on these platforms to take advantage of the advanced stability and features offered by components written with GNAT.

Ada's unique combination of object-oriented, high-level real-time control and concurrency features, coupled with the fundamental distinction between interface and implementation allows building the feature-rich and highly reliable objects required by component based development.

The GNATCOM home page is located at http://www.gnavi.org/gnatcom

GNATCOM Framework Overview

The GNATCOM framework allows for the creation of fully compliant COM objects providing full VTBL (virtual function table) support for custom interfaces in addition to the more limited automation (dynamic dispatch support through the COM interface IDispatch) used in most ActiveX controls. Additionally, BindCOM generates bindings to both custom interfaces (VTBL based) and interfaces offering the same performance boost of C++ over other languages in using COM objects but with Ada's careful type safety features.

The GNATCOM framework provides a thick bindings to COM/DCOM/COM+ for using pre-existing components, creating new components, COM event handling, automation types, Error handling, GUID creation and conversion, and reading type libraries.

Key GNATCOM Packages

  • GNATCOM

    Base package for the GNATCOM framework containing commonly used COM constants and automatic uninitializing of COM for the main thread.

  • GNATCOM.Initialize

    COM initialization and uninitialization

  • GNATCOM.GUID

    GUID creation and conversions

  • GNATCOM.Interface

    Thick binding to COM's IUnknown interface. Provides access to COM objects on local and remote systems, creation from Moniker strings (external representations of COM objects), automatic reference counting, and transparent querying for interfaces.

  • GNATCOM.Dispinterface

    Thick binding to Automation objects. Provides a thick binding to dispinterfaces and interfaces derived from IDispatch (dual interfaces) including subprograms to call by name and call by id.

  • GNATCOM.BSTR, GNATCOM.VARIANT, GNATCOM.SafeArray

    Thick bindings to COM/Automation types. Provides conversion to and from Ada types.

  • GNATCOM.Errors

    Provides HRESULT to exception mapping and mapping of HRESULTs to human readable strings.

  • GNATCOM.Events.Event_Object

    Dynamically creates a COM object supporting IDispatch that can be used with GNATCOM.Events subprograms to handle COM events.

  • GNATCOM.Create

    Base package of the GNATCOM COM/DCOM/COM+ creation support.

  • GNATCOM.Create.COM_Interface

    Provides an implementation of IUnknown for COM objects and provides the C++ style virtual function tables that comprise the COM binary standard for interfaces.

GNATCOM Tools Overview

  • MakeGUID

    Generates GUIDs (Global Unique IDs).

    Usage: MakeGUID Number_of_GUIDs

    C:\>MakeGUID {C41E5A70-F473-11D3-939E-0080C88637DE} C:\>MAKEGUID 3 {C41E5A70-F473-11D3-939E-0080C88637DE} {C41E5A71-F473-11D3-939E-0080C88637DE} {C41E5A72-F473-11D3-939E-0080C88637DE}

  • COMScope

    Generates documentation from type libraries (binary headers embedded in most COM objects).

    Usage: COMScope typelib typelib can be a type library file (.tlb) or any file with an embedded type library such as a COM object (.dll, .ocx, .exe)

    C:\>COMScope C:\winnt\system32\mshtml.tlb >IE5.txt C:\>COMScope C:\winnt\system32\msxml.dll >XML.txt

    Would produce a file IE5.txt describing all the types, objects, and methods in the mshtml.tlb type library or msxml COM object.

  • BindCOM

    Generates bindings from type libraries embedded in COM objects or that describe DLLs (frequently developers package type libraries with regular DLLs.)

    Usage: BindCOM typelib base_package_name typelib can be a type library file (.tlb) or any file with an embedded type library such as a COM object (.dll, .ocx, .exe) or Usage: BindCOM typelib_GUID Major_Version Minor_Version typelib_GUID is the GUID for a type library, a LIBID. Major_Version is the major version of the the type library and minor version is the minimum minor version of the type library that should be used to generate a binding.

    C:\>BindCOM C:\winnt\system32\msxml.dll MSXML C:\>BindCOM {D63E0CE2-A0A2-11D0-9C02-00C04FC99C8E} 2 0

    Would both produce a file called MSXML.ads containing a thin binding to the MSXML COM object and MSXML-*_interface.ad?, MSXML-*_object.ad?, MSXML-*_event.ad? files with thick bindings to interfaces, dispinterfaces, and event interfaces respectively.

  • CreateCOM

    Generates a complete COM object from type libraries requiring only function bodies to be filled in.

    Usage: CreateCOM typelib base_package_name typelib can be a type library file (.tlb) or any file with an embedded type library such as a COM object (.dll, .ocx, .exe)

    C:\>BindCOM MyProj.tlb MyProj.tlb

    Would produce the following files:

    1. myproj-dll.ad? - The InProc (Dll) implementation files
    2. myproj-exe.adb - The LocalServer (Exe) implementation files
    3. myproj-remote.adb - An application that can register the COM object on remote machines.
    4. myproj.ads - Thin bindings and GUIDs
    5. myprojrc.rc - Windows resource file embedding the type library
    6. make.bat - Batch file that will compile the files

    There will be an additional spec and body for every COM object (CoClass) defined in the the type library in the format of myproj-*.ad?. Implementations of the COM objects are filled in to the function bodies in the myproj-*.adb files.

Sample GNATCOM Applications

GNATCOM comes with a number of sample applications that demonstrate how to use the GNATCOM framework and bindings created by the GNATCOM tools. Many of these applications require bindings be generated for COM components first. The batch file make.bat in the bindings directory will create the needed bindings.

The res directory contains any needed files to create the Win32 resource files for the samples.

  • NT_GNATFIND

    Demonstrates creating a GUI front end to a command line application using the Internet Explorer Web Browser Control and handling COM events.

    There are a number of different versions of this sample application (nt_gnatfind.adb) located in different directories.

    1. Samples/ Sample application using VTBL bindings
    2. Samples/Dispatch/ Sample application using dispinterface (IDispatch) bindings
    3. Samples/Dynamic/ Sample application using the GNATCOM frameworks binding to dispinterface with out any generated bindings.
  • Spin

    Demonstrates use of ActiveX GUI Controls using the Internet Explorer Web Browser Control as the ActiveX control container, COM events, and using COM from Ada tasks.

    There are a number of different versions of this sample application (spin.adb) located in different directories.

    1. Samples/ Sample application using VTBL bindings
    2. Samples/Dispatch/ Sample application using dispinterface (IDispatch) bindings
    3. Samples/Dynamic/ Sample application using the GNATCOM frameworks binding to dispinterface with out any generated bindings.
    4. Samples/GIT Sample application using an alternate method of using multiple tasks in with GNATCOM that demonstrates use of the Global Interface Table to pass interfaces across COM apartment boundaries.
  • ADO

    Demonstrates use of GNATCOM with ADO (Microsoft ActiveX Data Objects) to access an ODBC database.

    The example (ado2.adb) is in the Samples/ directory. It requires that an ODBC DSN be created with the name ADOTEST pointing to the Access database in the Samples/res directory adotest.mdb.

    The example (ado1.adb) is in the Samples/ directory. It uses the Access OLEDB provider to connect to an Access database instead of ODBC and does not require any ODBC or other configuration.

    The example (ado3.adb) is in the Samples/ directory. It uses a UDL file found in the Samples/res directory to configure the connection via OLEDB to the access datatbase. UDL files are created by creating a blank file with the extension .udl. Once the file is created double clicking on it brings up the configuration application. It may be necessary to modify the configuration in the udl file in order for the example to work.

  • JavaCall

    Demonstrates calling Java code by using the COM Java moniker.

    The example (javacall.adb) is located in the Samples/ directory.

  • MSMQ

    Demonstrates use of GNATCOM with Microsoft Message Queueing (MSMQ) one of the COM+ services available on Windows 2000 and with the Microsoft Option Pack 4.

    The server (msmq_server.adb) and client (msmq_client.adb) applications are in the Samples/ directory.

  • VB Examples

    Demonstrates methods of interfacing Ada code to Visual Basic.

    Two projects AdaToVB and VBtoAda are located under the Samples/VB/ directory.

GNATCOM Tutorial

This tutorial assumes basic knowledge of COM/DCOM/COM+, an understanding of Ada 95 and GNAT. It would be helpful to have read the COM/DCOM/COM+ with GNAT documentation first.

Creating a COM Object     
Using a COM Object     

Creating a COM Object

  1. Create IDL

    The first step is to create an IDL file that conforms to OLE Automation specifications. See COM/DCOM/COM+ with GNAT documentation for more information on creating compatible IDL files for use with GNAT.

    This tutorial uses the gnatexample.idl found in the Docs/Tutorial directory containing one COM object, GNATCOMClass, that has two interfaces, IGNATMessage (a dual interface) and IGNATStat (a custom COM interface).

  2. Compile IDL to a TypeLibrary

    Compile gnatexample.idl using MIDL included with Visual Studio and the Microsoft SDK tools. This will produce the typelibrary gnatexample.tlb and a number of .h and .c files that can be erased.

  3. Generate code for COM object

    Execute the following command:

    CreateCOM gnatexample.tlb GNATExample

    This will create all the code needed to implement the COM object.

  4. With support for dual interface

    Edit the file gnatexample-gnatcomclass.ads and add a with of the package GNATCOM.Create.IDispatch.

    with GNATCOM.Create.IDispatch;

    This will include support to implement the automation (IDispatch) portion of the interface IGNATMessage for the object.

  5. Add dual interface support to object

    Add an IDispatch_Type object to the class record GNATCOMClass_Type.

    type GNATCOMClass_Type is new GNATCOM.Create.COM_Interface.CoClass_Type (GUID_Map'Access) with record Data : aliased GNATCOM.Create.IDispatch.IDispatch_Type (IID_IGNATMessage'Access, LIBID_GNATCOMLibrary'Access, 1, 0); end record;

    The options for the IDispatch_Type are the dual interface IID, the type library and the major and minor version (see the specs for the IDispatch support for more information). The IIDs and the LIBID can be found in the root package GNATExample.ads.

  6. Fill in dual interface support methods

    In function IGNATMessage_GetTypeInfoCount replace the return GNATCOM.E_NOTIMPL; with:

    return GNATCOM.Create.IDispatch.GetTypeInfoCount (pctinfo);

    In function IGNATMessage_GetTypeInfo replace the return GNATCOM.E_NOTIMPL; with:

    return GNATCOM.Create.IDispatch.GetTypeInfo (Object.Data'Access, itinfo, pptinfo);

    In function IGNATMessage_GetIDsOfNames replace the return GNATCOM.E_NOTIMPL; with:

    return GNATCOM.Create.IDispatch.GetIDsOfNames (Object.Data'Access, rgszNames, cNames, rgdispid);

    In function IGNATMessage_Invoke replace the return GNATCOM.E_NOTIMPL; with:

    return GNATCOM.Create.IDispatch.Invoke (This, Object.Data'Access, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);

  7. Add data members to object

    Add members to the class record to store object instance data. In this case an integer variable is added to the record to keep count of the number of times members have been called of the IGNATMessage interface.

    type GNATCOMClass_Type is new GNATCOM.Create.COM_Interface.CoClass_Type (GUID_Map'Access) with record Data : aliased GNATCOM.Create.IDispatch.IDispatch_Type (IID_IGNATMessage'Access, LIBID_GNATCOMLibrary'Access, 1, 0); Count : Integer := 0; end record;

  8. Implement remaining COM object methods

    Add with Win32.User; to the package and then fill in the lines in bold in to the IGNATMessage_Beep function removing the old return GNATCOM.E_NOTIMPL; line.

    function IGNATMessage_Beep (This : access GNATCOM.Create.COM_Interface.COM_Interface_Type) return GNATCOM.Types.HRESULT is Object : Pointer_To_GNATCOMClass_Type := Pointer_To_GNATCOMClass_Type (This.CoClass); RetValue : Win32.BOOL; begin RetValue := Win32.WinUser.MessageBeep (Win32.WinUser.MB_ICONEXCLAMATION); Object.Count := Object.Count + 1; return GNATCOM.S_OK; end IGNATMessage_Beep;

    Add with GNATCOM.Utility; and with GNATCOM.BSTR to the package and fill in the lines in bold in to the IGNATMessage_MessageBox function removing the old return GNATCOM.E_NOTIMPL; line. (Note that Ada exceptions should never be allowed to propagate beyond the COM object.)

    function IGNATMessage_MessageBox (This : access GNATCOM.Create.COM_Interface.COM_Interface_Type; Message : GNATCOM.Types.BSTR) return GNATCOM.Types.HRESULT is Object : Pointer_To_GNATCOMClass_Type := Pointer_To_GNATCOMClass_Type (This.CoClass); begin GNATCOM.Utility.Message_Box ("GNATCOM", GNATCOM.BSTR.To_Ada (Message, False)); Object.Count := Object.Count + 1; return GNATCOM.S_OK; exception when others => return GNATCOM.E_FAIL; end IGNATMessage_MessageBox;

    Fill in the lines in bold in to the IGNATStat_Calls function removing the old return GNATCOM.E_NOTIMPL; line.

    function IGNATStat_Calls (This : access GNATCOM.Create.COM_Interface.COM_Interface_Type; NumberOfTimes : GNATCOM.Types.Pointer_To_int) return GNATCOM.Types.HRESULT is Object : Pointer_To_GNATCOMClass_Type := Pointer_To_GNATCOMClass_Type (This.CoClass); begin NumberOfTimes.all := Interfaces.C.Int (Object.Count); return GNATCOM.S_OK; end IGNATStat_Calls;

  9. Compile and Register Object

    Compile the COM object by running the generated make.bat file. Then register either the Dll version, by typing regsvr32 gnatexample-dll.dll or the Exe version, by typing gnatexample-exe /RegServer.

    The COM object is now ready for use.

Using a COM Object

  1. Create the binding

    Run BindCOM gnatexample.tlb GNATClient to create a binding to the COM object in the previous tutorial.

  2. Create main procedure

    Set up the basic client main procedure and add error handling to catch COM errors as shown in bold:

    with Ada.Exceptions; with GNAT.IO; use GNAT.IO; procedure Client is begin exception when E : others => Put_Line (Ada.Exceptions.Exception_Name (E)); Put_Line (Ada.Exceptions.Exception_Message (E)); end Client;

  3. Initialize COM

    Before using GNATCOM, the COM environment must be initialized. This is done by calling the procedure GNATCOM.Initialize.Initialize_COM at the start of the Client procedure.

    procedure Client is begin GNATCOM.Initialize.Initialize_COM;

  4. Declare an Interface Type

    Add code to with in the bindings for the interfaces that will be used and declare objects of those types.

    
    

    with GNATClient.IGNATMessage_Interface; use GNATClient.IGNATMessage_Interface; with GNATClient.IGNATStat_Interface; use GNATClient.IGNATStat_Interface; procedure Client is Messages : IGNATMessage_Type; Stats : IGNATStat_Type;

  5. Create Object

    Create the COM object by calling Create on one of the interfaces supported by the object.

    Create (Messages, GNATClient.CLSID_GNATCOMClass);

  6. Use object

    Once the object has been created methods can be called on the interface used to create the object, or a Query can be performed to access other interfaces of the object.

    Beep (Messages); MessageBox (Messages, GNATCOM.BSTR.To_BSTR ("Hello World!")); Query (Stats, Messages); Put_Line ("IGNATMessage methods called" & Integer (Calls (Stats))'Img & " times.");

  7. Compile and run

    Compile the client code using gnatmake client and then run it. To use the object on a remote machine, first run the beep-remote.exe on the remote machine with the objects host machine name and the run the client on that machine. You may have to configure permissions on the host machine using the utility dcomcnfg.exe.

    client.adb :

    with Ada.Exceptions; with GNAT.IO; use GNAT.IO; with GNATCOM.Initialize; use GNATCOM.Initialize; with GNATCOM.BSTR; with GNATClient.IGNATMessage_Interface; use GNATClient.IGNATMessage_Interface; with GNATClient.IGNATStat_Interface; use GNATClient.IGNATStat_Interface; procedure Client is Messages : IGNATMessage_Type; Stats : IGNATStat_Type; begin GNATCOM.Initialize.Initialize_COM; Create (Messages, GNATClient.CLSID_GNATCOMClass); Beep (Messages); MessageBox (Messages, GNATCOM.BSTR.To_BSTR ("Hello World!")); Query (Stats, Messages); Put_Line ("IGNATMessage methods called" & Integer (Calls (Stats))'Img & " times."); exception when E : others => Put_Line (Ada.Exceptions.Exception_Name (E)); Put_Line (Ada.Exceptions.Exception_Message (E)); end Client;

Support for GNATCOM

See http://www.gnavi.org for support information

Index

ActiveX
ActiveX Data Objects
ADO
Automation
Automation Types
BindCOM
Binding
BSTR
COM Types
COMScope
CreateCOM
Creating COM objects
Dual Interface
Errors
Events <1>
Events <2>
Events
Examples <1>
Examples
Framework
Global Interface Table
GNATCOM
GNATCOM.BSTR
GNATCOM.Create
GNATCOM.Create.COM_Interface
GNATCOM.Dispinterface
GNATCOM.Errors
GNATCOM.Events
GNATCOM.Events.Event_Object
GNATCOM.GUID
GNATCOM.Initialize
GNATCOM.Interface
GNATCOM.IUnknown
GNATCOM.SafeArray
GNATCOM.VARIANT
GUID <1>
GUID
HRESULT
IDispatch
Interface
Internet Explorer
Introduction
IUnknown
J++
Java
JavaCall
JVM
MakeGUID
Microsoft Message Queueing
Moniker
MSMQ
NT_GNATFIND
Packages
SafeArray
Samples <1>
Samples
Spin
Support
Tasks
Threads
VARIANT
Visual Basic

This document was generated using GNU Makeinfo version 1.68


(c) 1999-2004 All Rights Reserved David Botton