comp.lang.ada
 help / color / mirror / Atom feed
* Ada to C interfacing with access on unconstrained array
@ 2009-10-20 13:07 dhenry
  2009-10-20 16:11 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: dhenry @ 2009-10-20 13:07 UTC (permalink / raw)


Hello,

I am trying to interface C with Ada: I want to call an Ada procedure
from C.
The Ada procedure takes as parameter a record, containing some
integers and
fat access types ("access all").

Ideally, I'd like to have no copy during the interfacing between Ada
and C.

Here is the Ada code:

--------------------------------------------------
package Foo is

   type Nut_Type is
      record
         Diameter : Integer;
         Weight   : Integer;
         Age      : Integer;
      end record;

   type Nut_Array_Type is array (Positive range <>) of Nut_Type;
   type Nut_Array_Access is access Nut_Array_Type;

   type Coco_Type is
      record
         X    : Integer;
         Y    : Integer;
         Nuts : Nut_Array_Access;
      end record;

   -- This is the procedure I want to be executed from C
   procedure Climb (Coco : in Coco_Type);

end Foo;
--------------------------------------------------
package body Foo is

   procedure Climb (Coco : in Coco_Type) is
   begin
      -- Climb on the coco...
   end Climb;

end Foo;
--------------------------------------------------

I want to use the Climb procedure. For interfacing, I can create an
intermediate
procedure C_Climb that fits well with C, but the Climb procedure can't
be changed.

The C_Climb procedure will take some data from C, and rebuild a
Coco_Type object
to give to the Climb procedure: "C program" => C_Climb => Climb.

My main problem is the Coco_Type.Nuts component, which is an access to
an
unconstrained array. I can't find how to map it without allocation/
copy data.

Here is an attempt to implement C_Climb:

--------------------------------------------------
with Interfaces.C;
with Interfaces.C.Pointers;

package Foo.C_Interface is

   type C_Nut_Type is
      record
         Diameter : Interfaces.C.int;
         Weight   : Interfaces.C.int;
         Age      : Interfaces.C.int;
      end record;

   type C_Nut_Array is array (Interfaces.C.int range <>) of aliased
C_Nut_Type;
   type C_Nut_Array_Access is access all C_Nut_Array;

   package C_Nut_Pointers is
      new Interfaces.C.Pointers (Interfaces.C.int, C_Nut_Type,
C_Nut_Array, (0, 0, 0));

   procedure Climb_C (C_X    : in Interfaces.C.int;
                      C_Y    : in Interfaces.C.int;
                      C_Nuts : in C_Nut_Pointers.Pointer;
                      C_Len  : in Interfaces.C.int);

   pragma Export (C, Climb_C, "climb");

end Foo.C_Interface;
--------------------------------------------------
package body Foo.C_Interface is

   procedure Climb_C (C_X    : in Interfaces.C.int;
                      C_Y    : in Interfaces.C.int;
                      C_Nuts : in C_Nut_Pointers.Pointer;
                      C_Len  : in Interfaces.C.int) is

      subtype My_Nuts is C_Nut_Array (1 .. C_Len);
      type My_Nuts_Access is access all My_Nuts;

      Nuts : aliased My_Nuts;
      for Nuts'Address use C_Nuts.all'Address;

      Nuts_Ptr : My_Nuts_Access := Nuts'Unchecked_Access;

      Coco : Coco_Type;
   begin
      Coco.X    := Integer (C_X);
      Coco.Y    := Integer (C_Y);

      -- How do I connect this access with my C pointer C_Nuts?
      Coco.Nuts := Nuts_Ptr; -- FAIL because My_Nuts_Access is not an
Nut_Array_Access

      Climb (Coco);
   end Climb_C;

end Foo.C_Interface;
--------------------------------------------------

Currently, the only way I found is to declare a Nut_Array_Access and
allocate memory with new:

Nuts_Ptr : Nut_Array_Access := new Nut_Array_Type (1 .. Integer
(C_Len));

So I can write "Coco.Nuts := Nuts_Access;". But I must fill
Nuts_Access.all with C_Nuts' data, and
that's what I'd like to avoid.

Any idea on the interfacing is welcome.

Yours,
David.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 13:07 Ada to C interfacing with access on unconstrained array dhenry
@ 2009-10-20 16:11 ` Dmitry A. Kazakov
  2009-10-21  9:25   ` dhenry
  2009-10-20 16:24 ` Adam Beneschan
  2009-10-20 18:40 ` tmoran
  2 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-20 16:11 UTC (permalink / raw)


On Tue, 20 Oct 2009 06:07:18 -0700 (PDT), dhenry wrote:

> I am trying to interface C with Ada: I want to call an Ada procedure
> from C.

When you pass a pointer to a C array to Ada you have to copy all elements
of the array when the types are not compatible, as they are according to
what you wrote. Therefore your interface must copy/marshal the parameters,
sorry.

The best thing you could do is to avoid pool memory allocation.

BTW, why

   type Coco_Type is record
      X : Integer;
      Y : Integer;
      Nuts : Nut_Array_Access;
   end record;

and not

   type Coco_Type (Size : Natural) is record
      X : Integer;
      Y : Integer;
      Nuts : Nut_Array_Type (1..Size);
   end record;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 13:07 Ada to C interfacing with access on unconstrained array dhenry
  2009-10-20 16:11 ` Dmitry A. Kazakov
@ 2009-10-20 16:24 ` Adam Beneschan
  2009-10-20 18:40 ` tmoran
  2 siblings, 0 replies; 10+ messages in thread
From: Adam Beneschan @ 2009-10-20 16:24 UTC (permalink / raw)


On Oct 20, 6:07 am, dhenry <tfc.d...@gmail.com> wrote:
> Hello,
>
> I am trying to interface C with Ada: I want to call an Ada procedure
> from C.
> The Ada procedure takes as parameter a record, containing some
> integers and
> fat access types ("access all").
>
> Ideally, I'd like to have no copy during the interfacing between Ada
> and C.

David,

Unfortunately, I don't think there's a solution.  The reason is that
on some implementations, the Nut_Array_Access, which is an access to
an unconstrained array, is implemented by making sure that a vector
containing the bounds is adjacent to the array data, and having the
access type be the address of the array data or perhaps the address of
the bounds, or something like that.  That means that if you have an
area of memory consisting just of data array, with no bound vector
adjacent to it, you can't convert the location to an access-to-
unconstrained-array type without copying the data.

                                            -- Adam


> Here is the Ada code:
>
> --------------------------------------------------
> package Foo is
>
>    type Nut_Type is
>       record
>          Diameter : Integer;
>          Weight   : Integer;
>          Age      : Integer;
>       end record;
>
>    type Nut_Array_Type is array (Positive range <>) of Nut_Type;
>    type Nut_Array_Access is access Nut_Array_Type;
>
>    type Coco_Type is
>       record
>          X    : Integer;
>          Y    : Integer;
>          Nuts : Nut_Array_Access;
>       end record;
>
>    -- This is the procedure I want to be executed from C
>    procedure Climb (Coco : in Coco_Type);
>
> end Foo;
> --------------------------------------------------
> package body Foo is
>
>    procedure Climb (Coco : in Coco_Type) is
>    begin
>       -- Climb on the coco...
>    end Climb;
>
> end Foo;
> --------------------------------------------------
>
> I want to use the Climb procedure. For interfacing, I can create an
> intermediate
> procedure C_Climb that fits well with C, but the Climb procedure can't
> be changed.
>
> The C_Climb procedure will take some data from C, and rebuild a
> Coco_Type object
> to give to the Climb procedure: "C program" => C_Climb => Climb.
>
> My main problem is the Coco_Type.Nuts component, which is an access to
> an
> unconstrained array. I can't find how to map it without allocation/
> copy data.
>
> Here is an attempt to implement C_Climb:
>
> --------------------------------------------------
> with Interfaces.C;
> with Interfaces.C.Pointers;
>
> package Foo.C_Interface is
>
>    type C_Nut_Type is
>       record
>          Diameter : Interfaces.C.int;
>          Weight   : Interfaces.C.int;
>          Age      : Interfaces.C.int;
>       end record;
>
>    type C_Nut_Array is array (Interfaces.C.int range <>) of aliased
> C_Nut_Type;
>    type C_Nut_Array_Access is access all C_Nut_Array;
>
>    package C_Nut_Pointers is
>       new Interfaces.C.Pointers (Interfaces.C.int, C_Nut_Type,
> C_Nut_Array, (0, 0, 0));
>
>    procedure Climb_C (C_X    : in Interfaces.C.int;
>                       C_Y    : in Interfaces.C.int;
>                       C_Nuts : in C_Nut_Pointers.Pointer;
>                       C_Len  : in Interfaces.C.int);
>
>    pragma Export (C, Climb_C, "climb");
>
> end Foo.C_Interface;
> --------------------------------------------------
> package body Foo.C_Interface is
>
>    procedure Climb_C (C_X    : in Interfaces.C.int;
>                       C_Y    : in Interfaces.C.int;
>                       C_Nuts : in C_Nut_Pointers.Pointer;
>                       C_Len  : in Interfaces.C.int) is
>
>       subtype My_Nuts is C_Nut_Array (1 .. C_Len);
>       type My_Nuts_Access is access all My_Nuts;
>
>       Nuts : aliased My_Nuts;
>       for Nuts'Address use C_Nuts.all'Address;
>
>       Nuts_Ptr : My_Nuts_Access := Nuts'Unchecked_Access;
>
>       Coco : Coco_Type;
>    begin
>       Coco.X    := Integer (C_X);
>       Coco.Y    := Integer (C_Y);
>
>       -- How do I connect this access with my C pointer C_Nuts?
>       Coco.Nuts := Nuts_Ptr; -- FAIL because My_Nuts_Access is not an
> Nut_Array_Access
>
>       Climb (Coco);
>    end Climb_C;
>
> end Foo.C_Interface;
> --------------------------------------------------
>
> Currently, the only way I found is to declare a Nut_Array_Access and
> allocate memory with new:
>
> Nuts_Ptr : Nut_Array_Access := new Nut_Array_Type (1 .. Integer
> (C_Len));
>
> So I can write "Coco.Nuts := Nuts_Access;". But I must fill
> Nuts_Access.all with C_Nuts' data, and
> that's what I'd like to avoid.
>
> Any idea on the interfacing is welcome.
>
> Yours,
> David.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 13:07 Ada to C interfacing with access on unconstrained array dhenry
  2009-10-20 16:11 ` Dmitry A. Kazakov
  2009-10-20 16:24 ` Adam Beneschan
@ 2009-10-20 18:40 ` tmoran
  2009-10-21  3:29   ` John B. Matthews
  2 siblings, 1 reply; 10+ messages in thread
From: tmoran @ 2009-10-20 18:40 UTC (permalink / raw)


>  type Nut_Array_Type is array (Positive range <>) of Nut_Type;
  C has no concept of an unconstrained array - only pointers to the
start of a length-less array.  The usual way to handle this is to
declare the Ada array constrained, but with a "sufficiently large"
constraint.  You can pass (a pointer to) such an array between C
and Ada.  You lose bounds checking on the Ada side, but you can
fudge that by renaming the actual slice.
So how about:

   type Nut_Array_Type is array (Positive range <>) of Nut_Type;
   subtype C_Nut_Array_Type is Nut_Array_Type(Positive);
   type C_Nut_Array_Access is access C_Nut_Array_Type;

   type Coco_Type is
      record
         X    : Integer;
         Y    : Integer;
         Nuts : C_Nut_Array_Access;
      end record;

   -- This is the procedure I want to be executed from C
   procedure Climb (Coco : in Coco_Type);
   ...
package body Foo is

   procedure Climb (Coco : in Coco_Type) is
     Coco_Nuts : renames Coco.Nuts.all(1 .. actual_length);
   begin



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 18:40 ` tmoran
@ 2009-10-21  3:29   ` John B. Matthews
  2009-10-21  9:29     ` dhenry
  0 siblings, 1 reply; 10+ messages in thread
From: John B. Matthews @ 2009-10-21  3:29 UTC (permalink / raw)


In article <hbl074$deo$1@aioe.org>, tmoran@acm.org wrote:

> >  type Nut_Array_Type is array (Positive range <>) of Nut_Type;
>   C has no concept of an unconstrained array - only pointers to the
> start of a length-less array.  The usual way to handle this is to 
> declare the Ada array constrained, but with a "sufficiently large" 
> constraint.  You can pass (a pointer to) such an array between C and 
> Ada.  You lose bounds checking on the Ada side, but you can fudge 
> that by renaming the actual slice.
> So how about:
> 
>    type Nut_Array_Type is array (Positive range <>) of Nut_Type;
>    subtype C_Nut_Array_Type is Nut_Array_Type(Positive);
>    type C_Nut_Array_Access is access C_Nut_Array_Type;
> 
>    type Coco_Type is
>       record
>          X    : Integer;
>          Y    : Integer;
>          Nuts : C_Nut_Array_Access;
>       end record;
> 
>    -- This is the procedure I want to be executed from C
>    procedure Climb (Coco : in Coco_Type);
>    ...
> package body Foo is
> 
>    procedure Climb (Coco : in Coco_Type) is
>      Coco_Nuts : renames Coco.Nuts.all(1 .. actual_length);
>    begin

David: GNAT implements a convenient pragma that's especially helpful for 
this approach. Given a procedure such as

   procedure Climb (Coco_Rec : Coco_Type; Length : Positive);

One can export the procedure

   pragma Convention(C, Climb);
   pragma Export_Procedure(
      Internal        => Climb,
      External        => climb,
      Parameter_Types => (Coco_Type, Positive),
      Mechanism       => (Value, Value));

Then in C, one can write

#define MAX_NUTS 10

struct Nut_Type {
   int Diameter;
   int Weight;
   int Age;
};
struct Nut_Type Nuts[MAX_NUTS];

struct Coco_Type {
   int X;
   int Y;
   struct Nut_Type *Nuts;
} Coco_Rec = { 1, 2, &Nuts[0] };

and invoke

   climb(Coco_Rec, MAX_NUTS);

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 16:11 ` Dmitry A. Kazakov
@ 2009-10-21  9:25   ` dhenry
  2009-10-21 12:09     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: dhenry @ 2009-10-21  9:25 UTC (permalink / raw)


On 20 oct, 18:11, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> BTW, why
>
>    type Coco_Type is record
>       X : Integer;
>       Y : Integer;
>       Nuts : Nut_Array_Access;
>    end record;
>
> and not
>
>    type Coco_Type (Size : Natural) is record
>       X : Integer;
>       Y : Integer;
>       Nuts : Nut_Array_Type (1..Size);
>    end record;

Well, I quickly tested the discriminant version of Coco_Type with my
application needs, and indeed I could use a discriminant to replace
the access. So I may reconsider my Coco_Type definition.

Would the discriminant version help me for my Ada->C interfacing?

Thanks,
David.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-21  3:29   ` John B. Matthews
@ 2009-10-21  9:29     ` dhenry
  2009-10-21 14:16       ` John B. Matthews
  0 siblings, 1 reply; 10+ messages in thread
From: dhenry @ 2009-10-21  9:29 UTC (permalink / raw)


On 21 oct, 05:29, "John B. Matthews" <nos...@nospam.invalid> wrote:
> David: GNAT implements a convenient pragma that's especially helpful for
> this approach. Given a procedure such as
>
>    procedure Climb (Coco_Rec : Coco_Type; Length : Positive);
>
> One can export the procedure
>
>    pragma Convention(C, Climb);
>    pragma Export_Procedure(
>       Internal        => Climb,
>       External        => climb,
>       Parameter_Types => (Coco_Type, Positive),
>       Mechanism       => (Value, Value));

Interesting.
But how does this pragma would cope with the access on unconstrained
array?

Yours,
David.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-21  9:25   ` dhenry
@ 2009-10-21 12:09     ` Dmitry A. Kazakov
  2009-10-21 12:14       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-21 12:09 UTC (permalink / raw)


On Wed, 21 Oct 2009 02:25:52 -0700 (PDT), dhenry wrote:

> On 20 oct, 18:11, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> BTW, why
>>
>> � �type Coco_Type is record
>> � � � X : Integer;
>> � � � Y : Integer;
>> � � � Nuts : Nut_Array_Access;
>> � �end record;
>>
>> and not
>>
>> � �type Coco_Type (Size : Natural) is record
>> � � � X : Integer;
>> � � � Y : Integer;
>> � � � Nuts : Nut_Array_Type (1..Size);
>> � �end record;
> 
> Well, I quickly tested the discriminant version of Coco_Type with my
> application needs, and indeed I could use a discriminant to replace
> the access. So I may reconsider my Coco_Type definition.
> 
> Would the discriminant version help me for my Ada->C interfacing?

No. It could only if the types you use would have C convention of the
parameters you are dealing with.

The problem is not how Nut_Array_Type is constrained, but what are its
elements. For example:

   type Nut_Type is record
      Diameter : int;
      Weight   : int;
      Age      : int;
   end record;
   pragma Convention (C, Nut_Type);

   type Nut_Type_Ptr is access all Nut_Type;
   pragma Convention (C, Nut_Type_Ptr);
   
   type Nut_Array_Type is array (Positive range <>) of aliased Nut_Type;
   pragma Convention (C, Nut_Array_Type);
   
   procedure Climb_C
             (  X    : int;
                Y    : int;
                Nuts : Nut_Type_Ptr;
                Len  : unsigned
             );
   pragma Export (C, Climb_C);

This sort of Climb_C can be called from C. Inside it you can call Climb
passing the array "as-is", provided Climb used the type Nut_Array_Type:

   procedure Climb (X, Y : int; Nuts : Nut_Array_Type);

   procedure Climb_C
             (  X    : int;
                Y    : int;
                Nuts : Nut_Type_Ptr;
                Len  : unsigned
             )  is
      subtype Actual_Array_Type is Nut_Array_Type (1..Natural (Len));
      Actual_Array : Actual_Array_Type;
      for Actual_Array'Address use Nuts.all'Address;
   begin
      Climb (X, Y, Actual_Array);
         -- Normally, this should not copy Actual_Array upon subtype
         -- conversion (from Actual_Array_Type to Nut_Array_Type)
   end Climb_C;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-21 12:09     ` Dmitry A. Kazakov
@ 2009-10-21 12:14       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2009-10-21 12:14 UTC (permalink / raw)


On Wed, 21 Oct 2009 14:09:51 +0200, Dmitry A. Kazakov wrote:

> On Wed, 21 Oct 2009 02:25:52 -0700 (PDT), dhenry wrote:
> 
>> On 20 oct, 18:11, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>> wrote:
>>> BTW, why
>>>
>>> � �type Coco_Type is record
>>> � � � X : Integer;
>>> � � � Y : Integer;
>>> � � � Nuts : Nut_Array_Access;
>>> � �end record;
>>>
>>> and not
>>>
>>> � �type Coco_Type (Size : Natural) is record
>>> � � � X : Integer;
>>> � � � Y : Integer;
>>> � � � Nuts : Nut_Array_Type (1..Size);
>>> � �end record;
>> 
>> Well, I quickly tested the discriminant version of Coco_Type with my
>> application needs, and indeed I could use a discriminant to replace
>> the access. So I may reconsider my Coco_Type definition.
>> 
>> Would the discriminant version help me for my Ada->C interfacing?
> 
> No. It could only if the types you use would have C convention of the
> parameters you are dealing with.
> 
> The problem is not how Nut_Array_Type is constrained, but what are its
> elements. For example:
> 
>    type Nut_Type is record
>       Diameter : int;
>       Weight   : int;
>       Age      : int;
>    end record;
>    pragma Convention (C, Nut_Type);
> 
>    type Nut_Type_Ptr is access all Nut_Type;
>    pragma Convention (C, Nut_Type_Ptr);
>    
>    type Nut_Array_Type is array (Positive range <>) of aliased Nut_Type;
>    pragma Convention (C, Nut_Array_Type);
>    
>    procedure Climb_C
>              (  X    : int;
>                 Y    : int;
>                 Nuts : Nut_Type_Ptr;
>                 Len  : unsigned
>              );
>    pragma Export (C, Climb_C);
> 
> This sort of Climb_C can be called from C. Inside it you can call Climb
> passing the array "as-is", provided Climb used the type Nut_Array_Type:
> 
>    procedure Climb (X, Y : int; Nuts : Nut_Array_Type);
> 
>    procedure Climb_C
>              (  X    : int;
>                 Y    : int;
>                 Nuts : Nut_Type_Ptr;
>                 Len  : unsigned
>              )  is
>       subtype Actual_Array_Type is Nut_Array_Type (1..Natural (Len));
>       Actual_Array : Actual_Array_Type;
>       for Actual_Array'Address use Nuts.all'Address;
>    begin
>       Climb (X, Y, Actual_Array);
>          -- Normally, this should not copy Actual_Array upon subtype
>          -- conversion (from Actual_Array_Type to Nut_Array_Type)
>    end Climb_C;

Or so:

   procedure Climb_C
             (  X    : int;
                Y    : int;
                Nuts : Nut_Type_Ptr;
                Len  : unsigned
             )  is
      Actual_Array : Nut_Array_Type (1..Natural (Len));
      for Actual_Array'Address use Nuts.all'Address;
      pragma Import (Ada, Actual_Array);
   begin
      Climb (X, Y, Actual_Array);
   end Climb_C;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-21  9:29     ` dhenry
@ 2009-10-21 14:16       ` John B. Matthews
  0 siblings, 0 replies; 10+ messages in thread
From: John B. Matthews @ 2009-10-21 14:16 UTC (permalink / raw)


In article 
<6f97c919-9535-4fa6-939d-9ec2cb927ed5@e34g2000vbc.googlegroups.com>,
 dhenry <tfc.duke@gmail.com> wrote:

> On 21 oct, 05:29, "John B. Matthews" <nos...@nospam.invalid> wrote:
> > David: GNAT implements a convenient pragma that's especially 
> > helpful for this approach. Given a procedure such as
> >
> >    procedure Climb (Coco_Rec : Coco_Type; Length : Positive);
> >
> > One can export the procedure
> >
> >    pragma Convention(C, Climb);
> >    pragma Export_Procedure(
> >       Internal        => Climb,
> >       External        => climb,
> >       Parameter_Types => (Coco_Type, Positive),
> >       Mechanism       => (Value, Value));
> 
> Interesting. But how does this pragma would cope with the access on 
> unconstrained array?

It doesn't use access to unconstrained array; Dmitry A. Kazakov's 
example is more apropos to that context. Instead, the approach relies on 
access to constrained array having a large constraint, as tmoran 
suggested. The former uses 'Address and the latter uses renames to match 
the C array/length pair to an Ada array.

Here is an example of the latter using type Natural as the large 
constraint:

package Callee is
   type Nut_Type is
      record
         Diameter : Integer;
         Weight   : Integer;
         Age      : Integer;
      end record;

   type Nut_Array_Type is array (Natural) of Nut_Type;
   type Nut_Array_Access is access Nut_Array_Type;

   type Coco_Type is
      record
         X    : Integer;
         Y    : Integer;
         Nuts : Nut_Array_Access;
      end record;

   procedure Climb(Coco_Rec : Coco_Type; Length : Positive);
   pragma Convention(C, Climb);
   pragma Export_Procedure(
      Internal        => Climb,
      External        => climb,
      Parameter_Types => (Coco_Type, Positive),
      Mechanism       => (Value, Value));

end Callee;

with Text_IO;
package body Callee is

procedure Climb(Coco_Rec : Coco_Type; Length : Positive) is
   Coco_Nuts : Nut_Array_Type renames Coco_Rec.Nuts.all(0 .. Length - 1);
begin
  Text_IO.Put_Line("Viewed from Ada.");
  Text_IO.Put_Line("( X, Y )" & Coco_Rec.X'Img & Coco_Rec.Y'Img);
  for I in Coco_Nuts'Range loop
     Text_IO.Put_Line("(" & I'Img & " )"
        & Coco_Nuts(I).Diameter'Img
        & Coco_Nuts(I).Weight'Img
        & Coco_Nuts(I).Age'Img);
  end loop;
end Climb;

end Callee;

/* caller.c */
#include <stdio.h>
#define MAX_NUTS 10

struct Nut_Type {
   int Diameter;
   int Weight;
   int Age;
};
struct Nut_Type Nuts[MAX_NUTS];

struct Coco_Type {
   int X;
   int Y;
   struct Nut_Type *Nuts;
} Coco_Rec = { 1, 2, &Nuts[0] };

int i;

main() {
   /* Initialize Ada */
   adainit();
 
   /* Process */
   printf("Initializing %i records in C.\n", MAX_NUTS);
   for (i = 0 ; i < MAX_NUTS; i++) {
      Coco_Rec.Nuts[i].Diameter = i;
      Coco_Rec.Nuts[i].Weight = i;
      Coco_Rec.Nuts[i].Age = i;
   }
   climb(Coco_Rec, MAX_NUTS);
 
   /* Finalize Ada */
   adafinal();
}

Dependencies:

caller: callee.ali caller.o
    gnatbind -n callee.ali
    gnatlink -o caller callee.ali caller.o

callee.ali: callee.adb callee.ads
    gnatmake -c callee

caller.o: caller.c
    gcc -c caller.c

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-10-21 14:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-20 13:07 Ada to C interfacing with access on unconstrained array dhenry
2009-10-20 16:11 ` Dmitry A. Kazakov
2009-10-21  9:25   ` dhenry
2009-10-21 12:09     ` Dmitry A. Kazakov
2009-10-21 12:14       ` Dmitry A. Kazakov
2009-10-20 16:24 ` Adam Beneschan
2009-10-20 18:40 ` tmoran
2009-10-21  3:29   ` John B. Matthews
2009-10-21  9:29     ` dhenry
2009-10-21 14:16       ` John B. Matthews

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