Next: Step 3 - Object Implementation, Previous: Step 1 - The Resource File, Up: The COM object implementation [Contents][Index]

#### 5.1.2 Step 2 - Base package

The top level package for implementing the COM object will contain global reference counters, GUID definitions, and types.

There are two main global reference counters needed for COM objects a component count and a server lock count. The component count is used to identify when to shutdown the server and the server lock provides a means to lock the server in memory to enhance performance when objects will be created and deleted frequently.

There are three types of GUID definitions needed, library ID, class IDs, and interface IDs. These are the GUIDs defined in the IDL for the library, coclass’es, and interface’s. For example:

    --  LIBID of library GNATCOMLibrary
    --  {45F9F480-787C-11D3-821C-52544C1913DE}

    LIBID_GNATCOMLibrary : aliased Win32.Objbase.IID :=
      (16#45F9F480#, 16#787C#, 16#11D3#,
        (char'Val (16#82#), char'Val (16#1C#),
         char'Val (16#52#), char'Val (16#54#),
         char'Val (16#4C#), char'Val (16#19#),
         char'Val (16#13#), char'Val (16#DE#)));

The types needed for implementation are access functions for every method used by the interfaces of the COM object including those used in the interfaces’ parents. Along with an interface type that will be the will be a an access parameter in the first position of every method. The interface type will contain the address of the instance data for the object and a reference count for the interface. This reference count allows for instances of the interface to automatically be deallocated from memory when the interface count reaches zero. For example:

    --  Access function types for IGNATStat

    type af_IGNATStat_Calls is access
      function (This          : access Interface;
                NumberOfTimes : access Interfaces.C.int)
      return HRESULT;
    pragma Convention (StdCall, af_IGNATStat_Calls);

    type Interface is record
       Vtbl      : System.Address;
       Ref_Count : aliased Win32.LONG := 1;
       CoClass   : System.Address;
    end record;
    pragma Convention (C, Interface);

Additionally a boolean variable is added to the package indicating if the object is in an InProc Server or a Local Server, and a procedure called `Can_Close` that is called every time an object is released, so that in the event the object is contained in a Local Server, if all objects are released and there are no server locks, the server can close itself down. The implementation of `Can_Close` is:

    procedure Can_Close is
       bResult : Win32.BOOL;
    begin
       if Server_Lock_Count = 0
         and then Component_Count = 0
         and then InProcServer /= True
       then
          bResult := Win32.Winuser.PostThreadMessage
            (Win32.Winbase.GetCurrentThreadId,
             Win32.Winuser.WM_QUIT,
             0,
             0);
       end if;
    end Can_Close;

Next: Step 3 - Object Implementation, Previous: Step 1 - The Resource File, Up: The COM object implementation [Contents][Index]