* Re: calling ada from c with an array param
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
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Jan Andres @ 2009-09-20 19:59 UTC (permalink / raw)
On 2009-09-20, Mike <michael_tabak@yahoo.com> 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. I read you should not use an
> unconstrained array so I tried the following
>
> The c program is
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> extern void adainit (void);
> extern void adafinal (void);
> extern int conjunc (float[], int);
>
> int main (int argc, char *argv[])
> {
>
> int i;
> float b[3] = {0.0, 0.0, 0.0};
>
> adainit();
>
> conjunc(a, 4);
>
> for (i = 0; i < 3; i++)
> {
> printf("a[%d] = %f, b[%d] = %f\n", i, a[i], b[i]);
> }
>
> adafinal();
>
> }
>
> The .ads file is
>
> -- conjunc.ads
> package conjunc is
> type Float_Array is array (Integer range <>) of Float;
> subtype Contrained_Float_Array is Float_Array (1 .. Integer'Last);
> procedure conj (A: in out Constrained_Float_Array; Len: in
> Integer);
> pragma Export (C, conj, "conj");
> end conjunc;
>
> and the procedure .adb file is
>
> -- conjunc.adb
> package body conjunc is
> type Float_Array is array (Integer range <>) of Float;
> subtype Contrained_Float_Array is Float_Array (1 .. Integer'Last);
> procedure conj (A: in out Constrained_Float_Array; Len :in Integer)
> is
> begin
> A(1) := 99;
> A(2) := 100;
> A(3) := 101;
> A(4) := 102;
> end conj;
> end conjunc;
>
>
> The procedure to build it is first gcc -c cjserver.c which works fine,
> then gnatmake -c conjunc.adb which gives me the following error:
>
> conjunc.adb:3:09: "Float_Array" conflicts with declaration at
> conjunc.ads:3
> conjunc.adb:4:12: "Contrained_Float_Array" conflicts with declaration
> at conjunc.ads:4
All declarations from the package spec (.ads file) are automatically
visible in the package body (.adb file), so there's no point in
repeating them there.
And, unlike C in some cases, Ada generally does not allow repeated
declarations of the same entity even if they are equivalent.
> conjunc.ads:5:30: "Constrained_Float_Array" is undefined (more
> references follow)
> conjunc.ads:5:30: possible misspelling of "Contrained_Float_Array"
It's true -- there is a typo (missing 's').
HTH
Jan
--
Jan Andres <jandres@gmx.net>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: calling ada from c with an array param
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
2009-09-21 8:08 ` Dmitry A. Kazakov
2009-09-21 17:29 ` Jeffrey R. Carter
2009-09-21 19:58 ` sjw
3 siblings, 1 reply; 6+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-21 8:04 UTC (permalink / raw)
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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: calling ada from c with an array param
2009-09-21 8:04 ` Dmitry A. Kazakov
@ 2009-09-21 8:08 ` Dmitry A. Kazakov
0 siblings, 0 replies; 6+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-21 8:08 UTC (permalink / raw)
On Mon, 21 Sep 2009 10:04:58 +0200, Dmitry A. Kazakov wrote:
> 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;
I forgot to add this:
pragma Convention (C, C_Float_Array);
> 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: calling ada from c with an array param
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
@ 2009-09-21 17:29 ` Jeffrey R. Carter
2009-09-21 19:58 ` sjw
3 siblings, 0 replies; 6+ messages in thread
From: Jeffrey R. Carter @ 2009-09-21 17:29 UTC (permalink / raw)
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. I read you should not use an
> unconstrained array so I tried the following
You should not be messing with mixed-language programming until you are no
longer new to Ada. Much of your problem comes from the fact that you don't
understand packages yet.
When you do get to mixed-language programming, you should never use any types in
your code that interfaces with C that are not declared in Interfaces.C and its
children, or that are declared to be Convention C.
--
Jeff Carter
"It's all right, Taggart. Just a man and a horse being hung out there."
Blazing Saddles
34
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: calling ada from c with an array param
2009-09-20 19:38 calling ada from c with an array param Mike
` (2 preceding siblings ...)
2009-09-21 17:29 ` Jeffrey R. Carter
@ 2009-09-21 19:58 ` sjw
3 siblings, 0 replies; 6+ messages in thread
From: sjw @ 2009-09-21 19:58 UTC (permalink / raw)
On Sep 20, 8:38 pm, Mike <michael_ta...@yahoo.com> wrote:
> extern void adainit (void);
> extern void adafinal (void);
> extern int conjunc (float[], int);
> -- conjunc.ads
> package conjunc is
> type Float_Array is array (Integer range <>) of Float;
> subtype Contrained_Float_Array is Float_Array (1 .. Integer'Last);
> procedure conj (A: in out Constrained_Float_Array; Len: in
> Integer);
> pragma Export (C, conj, "conj");
> end conjunc;
Is the C name of your function to be 'conjunc' (as in the C above) or
'conj' (as in the Ada)?
(probably a good idea to avoid using the name of the Ada package!)
^ permalink raw reply [flat|nested] 6+ messages in thread