comp.lang.ada
 help / color / mirror / Atom feed
* calling ada from c with an array param
@ 2009-09-20 19:38 Mike
  2009-09-20 19:59 ` Jan Andres
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Mike @ 2009-09-20 19:38 UTC (permalink / raw)


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
conjunc.ads:5:30: "Constrained_Float_Array" is undefined (more
references follow)
conjunc.ads:5:30: possible misspelling of "Contrained_Float_Array"

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

Thanks
Mike



^ 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
                   ` (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

end of thread, other threads:[~2009-09-21 19:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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

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