comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: calling ada from c with an array param
Date: Mon, 21 Sep 2009 10:04:58 +0200
Date: 2009-09-21T10:04:58+02:00	[thread overview]
Message-ID: <19zw9zf5j7p5b.vpt4c3xvlsaa.dlg@40tude.net> (raw)
In-Reply-To: 0208bf86-cba9-45db-a43c-53c249bf9ae6@l34g2000vba.googlegroups.com

On Sun, 20 Sep 2009 12:38:04 -0700 (PDT), Mike wrote:

> I'm new to Ada so I'm trying to expand a simple c example that passed
> primitive types to an Ada
> function. I'm trying to call an ada procedure from a c program with an
> in out float array using GNAT.

Your idea is in general OK, and a huge flat array could be used to
interface C. Alternatively there is Interfaces.C.Pointers package in the
standard library intended for this purpose. (Since C does not have arrays
you cannot pass them to Ada (:-))

In general when interfacing to C, your program shall use C types as
provided by the package Interfaces.C. For example, there is no warranty to
consider Ada's Float an equivalent to C's float.

> Obviously there is a problem declaring the array, but I'm not sure
> where it goes. Can someone help?

Here is a modified variant of your attempt:
-------------- main.c ----------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void conjunc (float[], int);

int main (int argc, char *argv[])
{
   int i;
   float a[4] = {0.0, 0.0, 0.0, 0.0};

   conjunc(a, sizeof(a)/sizeof(float));

   for (i = 0; i <= 3; i++)
   {
     printf("a[%d] = %f ", i, a[i]);
   }
}

I will illustrate both approaches.

1. Interfaces.C.Pointers:

--------- conjunc.ads --------------------
with Interfaces.C;  use Interfaces.C;
with Interfaces.C.Pointers;

package conjunc is
   type C_Float_Array is array (int range <>) of aliased C_Float; -- Sic!
   package C_Float_Pointers is
      new Interfaces.C.Pointers (int, C_Float, C_Float_Array, 0.0);
   use C_Float_Pointers;
   procedure conj (A : Pointer; Len: int);
   pragma Export (C, conj, "conjunc");
end conjunc;
--------- conjunc.adb --------------------
package body conjunc is
   procedure conj (A : Pointer; Len: int) is
      Data : C_Float_Array (1..Len);
      for Data'Address use A.all'Address;
      pragma Import (Ada, Data); -- Not necessary here, but cleaner
   begin
      Data (1) := 99.0;
      Data (2) := 100.0;
      Data (3) := 101.0;
      Data (4) := 102.0;
   end conj;
end conjunc;
------------------------------------------
Note that C_Float_Array is an array of aliased C_Float. C_Float is declared
in Interfaces.C and must be same as C's float. To have it aliased is
required because in C you can get pointer to each "array" element, for
obvious reason of not having arrays. In Ada it is in general wrong because
an array can be packed. Within the body of conjunc the pointer passed from
C is mapped to a constrained array of specified length (Data). You can also
use pointer arithmetic as you would in C, but it would be to tedious. So I
just declared Data of desired length located where the pointer points.

To build this with GNAT, do:

gcc -c main.c
gnatmake -c conjunc.adb
gnatbind -n conjunc.ali
gnatlink conjunc.ali main.o -o main

2. Here is a variant based on flat arrays:
--------- conjunc.ads --------------------
with Interfaces.C;  use Interfaces.C;

package conjunc is
   type C_Float_Array is array (int range <>) of aliased C_Float;
   subtype Flat_C_Float_Array is C_Float_Array (1..int'Last);
   procedure conj (A : in out Flat_C_Float_Array; Len: int);
   pragma Export (C, conj, "conjunc");
end conjunc;
--------- conjunc.adb --------------------
package body conjunc is
   procedure conj (A : in out Flat_C_Float_Array; Len: int) is
   begin
      A (1) := 99.0;
      A (2) := 100.0;
      A (3) := 101.0;
      A (4) := 102.0;
   end conj;
end conjunc;

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



  parent reply	other threads:[~2009-09-21  8:04 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-20 19:38 calling ada from c with an array param Mike
2009-09-20 19:59 ` Jan Andres
2009-09-21  8:04 ` Dmitry A. Kazakov [this message]
2009-09-21  8:08   ` Dmitry A. Kazakov
2009-09-21 17:29 ` Jeffrey R. Carter
2009-09-21 19:58 ` sjw
replies disabled

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