comp.lang.ada
 help / color / mirror / Atom feed
From: "Nick Roberts" <Nick.Roberts@dial.pipex.com>
Subject: Re: Ada address of operator?
Date: 1999/02/10
Date: 1999-02-10T00:00:00+00:00	[thread overview]
Message-ID: <79s62s$7vn$1@plug.news.pipex.net> (raw)
In-Reply-To: 36C02FFC.458368B1@aston.ac.uk

Danny,

In this instance, you do not need to declare a pointer-to-a-pointer type in
Ada. Instead, use the fact that Ada interprets 'out' parameters as pointers
when interfacing to C to provide the second level of indirection (see RM95
B.1, B.2, and B.3, especially B.3(68)).

For example (completely contrived):

   type File_Handle is Interfaces.C.int;

   type File_Descriptor_Block is
      record
         Name_1, Name_2: Interfaces.C.char_array(1..11);
         ...
      end record;

   pragma Convention(C,File_Descriptor_Block);

   type File_Handle_Access is access all File_Handle;
   type File_Descriptor_Block_Access is access all File_Descriptor_Block;

   pragma Convention(C,File_Handle_Access);
   pragma Convention(C,File_Descriptor_Block_Access);

   function Get_FDB (Handle: in File_Handle_Access; FDBA: out
File_Descriptor_Block_Access) return File_Handle;

   pragma Import(C,Get_FDB,"GetFDB");

[Apologies for the horrible formatting btw.]

Note the assiduous use of pragma Convention, to (help to) ensure that Ada
entities are implemented in a way compatible with their C equivalents. If
you are lucky, the Ada compiler will not rearrange the components of a
record type which has the C convention applied to it (otherwise, you will
have to use a record representation clause - see RM95 13.5.1).

The parameter 'FDBA' is an 'out' parameter of an access type, so it will
correspond to a C 'pointer-to-a-pointer'. The corresponding C function
prototype could be:

   int GetFDB(int *phand, FDB **ppfdb);

I am assuming the parameter semantics of this function to be that the file
handle pointed to by 'phand' is passed into the function, and a pointer to
the file's FDB is passed out (into 'ppfdb'). (And the handle (or -1 for an
error) is returned by the function, as a convenience).

Back in Ada, the access value put into the parameter 'FDBA' can be assigned
to other objects of the same type without any further ado; record components
will be dereferenced automatically, otherwise the '.all' qualifier must be
added to cause dereferencing. For example (again totally contrived):

   declare
      FDBA: File_Descriptor_Block_Access;
      Vital_FDBA: File_Descriptor_Block_Access := null; -- to emphasise
initialisation
      Vital_FDB: File_Descriptor_Block;
   begin
      ...
      for i in Active_File_Index loop
         if Get_FDB(Active_File(i),FDBA) >= 0 then
            if ... then
               Vital_FDBA := FDBA;
            end if;
         end if;
      end loop;
      if Vital_FDBA /= null then
         -- at this point Vital_FDBA accesses one of the FDBs returned by
Get_FDB
         if Interfaces.C.To_Ada(Vital_FDBA.Name_1) /= "XYZDATA DAT" then
            Vital_FDB := Vital_FDBA.all; -- copies the FDB data itself
            ...
         end if;
      else
         ...
      end if;
   end;

Note, also, the style of Ada identifiers I use, which are typical for Ada
programming (although tastes vary, of course). I think I speak for pretty
well all Ada programmers in saying that the '.all' is one of the least liked
aspects of Ada syntax (but not the automatic dereferencing, which only a few
dislike).

One final point. It is often vitally important to check the validity of
parameters you pass into an external routine before making the call, and the
validity and status of output parameters afterwards. The reason why is that
these routines do not have recourse to the Ada exception mechanism to report
errors. For example, the above code does not check 'Active_File(i)' for
being null. It should.

-------------------------------------------
Nick Roberts    "The Prophylactic Didactic"
-------------------------------------------







  parent reply	other threads:[~1999-02-10  0:00 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-02-09  0:00 Ada address of operator? Danny
1999-02-09  0:00 ` Niklas Holsti
1999-02-10  0:00 ` Nick Roberts [this message]
1999-02-12  0:00   ` Nick Roberts
1999-02-11  0:00 ` Matthew Heaney
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox