comp.lang.ada
 help / color / mirror / Atom feed
From: Ludovic Brenta <ludovic.brenta@insalien.org>
Subject: Re: C array to ada record interface
Date: Sat, 24 Jul 2004 20:48:34 +0200
Date: 2004-07-24T20:47:55+02:00	[thread overview]
Message-ID: <87iscdi6m5.fsf@insalien.org> (raw)
In-Reply-To: 404ee0af.0407221002.1cfdc21e@posting.google.com

 (Francisco Javier Loma Daza) writes:
> Jeffrey Carter wrote in message Francisco Javier Loma Daza wrote:
>> 
>> > struct
>> > {
>> >    int a,b,c:
>> >    int len;
>> >    struct b* arr;
>> > } A;
>> > 
>> > And I would love to interface in Ada with a record with a discriminant
>> > 
>> > type B_array(len: Positive) is record
>> >     arr: array of B(1..len);
>> > end record;
>> > 
>> > type A(len: Positive) is
>> >    a,b,c: Integer;
>> >    arr:   A(len);
>> > end record;
>> 
>> Assuming you meant
>> 
>>     Arr : B_Array (Len => Len);
>> 
>> this won't work. What you have from C is a pointer; the actual array may 
>>   not even be contiguous with the struct. You'll have to do something like
>> 
>> type B_Ptr is access all B;
>> pragma Convention (C, B_Ptr);
>> 
>> type A_Info is record
>>     A, B, C : Interfaces.C.Int;
>>     Len     : Interfaces.C.Int;
>>     Arr     : B_Ptr;
>> end record;
>> pragma Convention (C, A_Info);
>> 
>> You only use these types when talking directly to C. For the rest of 
>> your application, you use something like the record you presented, and 
>> have your operations that talk to C convert between the 2.
>
>
> Thanks, I think you understood well
>
> I would want to use some more ada like array, you suggest to implement
> that with accesors functions ... I was just wondering if it can be
> done, the Len + Arr part, to be set up as an Ada array ...

Yes, it can be done:

with Ada.Unchecked_Conversion;
function To_Ada_Array (Arr : in B_Ptr; Len : in Interfaces.C.int)
                       return B_Array is
   subtype Array_With_Known_Length is B_Array (1 .. Len);   

   function To_Ada is new Ada.Unchecked_Conversion
      (Source => B_Ptr, Target => Array_With_Known_Length);

begin
   -- ...
end To_Ada_Array;


In the begin/end block you have two possible strategies:

   return To_Ada (B_Ptr);

will return a B_Array where the Arr member has the same address (in
memory) as the original C array.  If you deallocate the C array, you
will get a Constraint_Error if you try to use the Ada array.  If you
want to avoid this, the other strategy is to return a copy:

   declare
      Input : Array_With_Known_Lengh := To_Ada (Arr);
      Result : B_Array (1 .. Len) := Input;
   begin
      return Result;
   end;

The advantage of having a copy is that Result.Arr has a different
address than the C array; thus you manage the memory separately for
the C and Ada arrays.  You can now safely deallocate the C array; the
Ada compiler will manage the memory for the Ada array for you, since
you declared it on the stack.

The disadvantage of this approach is that it requires more memory to
run; if the array is very large, it could become a problem.

HTH

(PS. I have not tried to compile my example code, so there may be
errors in it)

-- 
Ludovic Brenta.



  reply	other threads:[~2004-07-24 18:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-07-14 23:17 C array to ada record interface Francisco Javier Loma Daza
2004-07-15  0:36 ` Brian May
2004-07-15  1:23 ` Jeffrey Carter
2004-07-22 18:02   ` Francisco Javier Loma Daza
2004-07-24 18:48     ` Ludovic Brenta [this message]
2004-07-25 17:26       ` Francisco Javier Loma Daza
2004-07-25 19:28       ` tmoran
2004-07-26 21:42         ` Ludovic Brenta
2004-07-27 21:04           ` tmoran
2004-07-27 22:15             ` Martin Dowie
2004-07-28  2:42             ` Robert I. Eachus
2004-07-29  5:56               ` tmoran
2004-07-29 19:58                 ` Robert I. Eachus
replies disabled

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