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
next prev 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