From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,e39fb6aac207c1a4 X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news4.google.com!feeder.news-service.com!xlned.com!feeder1.xlned.com!npeer.de.kpn-eurorings.net!npeer-ng0.de.kpn-eurorings.net!newsfeed.arcor.de!newsspool1.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: calling ada from c with an array param Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <0208bf86-cba9-45db-a43c-53c249bf9ae6@l34g2000vba.googlegroups.com> Date: Mon, 21 Sep 2009 10:04:58 +0200 Message-ID: <19zw9zf5j7p5b.vpt4c3xvlsaa.dlg@40tude.net> NNTP-Posting-Date: 21 Sep 2009 10:04:58 CEST NNTP-Posting-Host: 1747812b.newsspool4.arcor-online.net X-Trace: DXC=dCI5VA>;_kgRYShQ66G`^:U X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:8413 Date: 2009-09-21T10:04:58+02:00 List-Id: 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 #include #include 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