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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 109fba,fd7e47dd49751091 X-Google-Attributes: gid109fba,public X-Google-Thread: 103376,fd7e47dd49751091 X-Google-Attributes: gid103376,public X-Google-Thread: 1014db,42a7529e47e4cb8d,start X-Google-Attributes: gid1014db,public From: nasser@apldbio.com (Nasser Abbasi) Subject: Re: on calling Ada from C/C++ Date: 1996/06/13 Message-ID: X-Deja-AN: 159921685 sender: news@biosys.apldbio.COM references: to: nasser@apldbio.com (Nasser Abbasi) followup-to: comp.lang.ada organization: Applied BioSystems newsgroups: comp.lang.ada,comp.lang.c++,comp.lang.c Date: 1996-06-13T00:00:00+00:00 List-Id: little more on this subject.. If you want to call more than one ada subprogram from C++, I found that gnatlink (the gnat ada linker) does not take more than .ALI file, this means that you can not have separate ada functions/procedure in separate files and have C++ call them (unless I missed something), the easy solution is to put them in one ada package, this way you can have one .ALI file , and the gnatlink is happy. Below is little larger example of a C++ main calling a number of Ada subprograms, also using arrays. the Interfaces.C package has usefull stuff for interfacing to C/C++, but it does not have converter functions to convert C arrays to Ada and visversa arrays where the array compononet is other than char,char_array,wchar_t, wchar_array, but it is easy to write these. So if you pass an array of int (say) to Ada, and you want Ada to process the array as starting from 1 not from 0, then you need to convert/"slide" over the array inside the Ada function before processing it, also to convert the array component types from the C++ int type to the Ada Integer type. Or you can just leave it the way it is starting from zero, and cast the array compononet to Integer from int. A simple function will do the conversion. Is there is way to slide the array over on the fly ? (since the array compononets are different types, one in standard.integer and one is Interfaces.C.int I could not do it on the fly, so I wrote a function, probably there is a more elegent way that this... Need to look more into this..) I happend to dislike arrays that start from 0, I think arrays that start from 1, as in Fortran say , are more natural to use, and also easier to process. The following are the steps used to build main, and the source code example. This example is just for testing/learning how to call Ada from C++, so please dont scream at me if you think it is not the most efficient. steps: 1. first I compile the C++ main gcc -c main.cc -I/usr/local/netshare/lib/g++-include 2. compile the ada package that contains all the ada functions/procedures that will be called from C++ gcc -c my_pkg.adb 3. bind my_pkg.ali (the .ali file is generated from step 2) : gnatbind -n my_pkg.ali 4. link everything togother (with the C++ libraries also offcourse) gnatlink -L/usr/local/netshare/lib my_pkg.ali main.o -lg++ -lstdc++ -o main main.cc ------ #include #include extern "C" { void Increment( int* ); int Sum( int[] , int ); int Sum_Version2( int[] , int ); void Modify( int[] , int ); void adainit(); void adafinal(); } main() { int i=0; int a[5]= {0,1,2,3,4}; adainit(); Increment(&i); // we pass address since it is declared IN OUT in ada cout<<" after calling Ada, i="<) of Integer; type C_Int_Array_type is array(integer range <>) of C.int; procedure Modify(A: in out C_Int_Array_type ; Len: in C.Size_t ); function Sum(A: in C_Int_Array_type ; Len: in C.Size_t ) return C.int; function Sum_version2(A: in C_Int_Array_type ; Len: in C.Size_t ) return C.int; procedure Increment(I:in out C.int); function To_Ada(A: in C_Int_Array_Type; Len: in C.Size_t) return Ada_Int_Array_type; end My_Pkg; my_pkg.adb ========== with Ada.Text_Io; use Ada.Text_Io; package body My_Pkg is -- -- -- function Sum(A: in C_Int_Array_type; Len : in C.Size_t ) return C.Int is The_Sum: Integer; Length: Integer := Integer(Len); begin The_Sum := 0; Put_Line("array from C++ has length " & integer'Image(Length)); for I in 0 .. Length-1 loop Put_line("array from C++ at index " & integer'Image(I) & " is " & C.int'Image(A(I))); The_Sum := The_Sum + Integer(A(I)); end loop; return C.Int(The_Sum); end Sum; pragma Export(C,Sum,"Sum"); -- -- -- function Sum_version2(A: in C_Int_Array_type; Len : in C.Size_t ) return C.Int is The_Sum: Integer; Length: Integer := Integer(Len); Ada_Int_Array: Ada_Int_Array_Type(1..Integer(Len)); begin Ada_Int_Array := To_Ada(A,len); The_Sum := 0; Put_Line("array from C++ has length " & integer'Image(Length)); for I in 1 .. Length loop The_Sum := The_Sum + Ada_Int_array(I); end loop; return C.Int(The_Sum); end Sum_version2; pragma Export(C,Sum_Version2,"Sum_Version2"); -- -- -- procedure Modify(A: in out C_Int_Array_type; Len: in C.Size_t ) is Length: Integer := Integer(Len); use Interfaces.C; begin for I in 1 .. Length loop A(I) := A(I) * 2; end loop; end Modify; pragma Export(C,MOdify,"Modify"); -- -- -- procedure Increment(I:in out C.int) is use Interfaces.C; begin Put_Line("Number passed in is" & C.int'Image(I)); I := I+1; end Increment; pragma Export(C,Increment,"Increment"); -- -- --- function To_Ada(A: in C_Int_Array_Type;Len: C.Size_t) return Ada_Int_Array_Type is Back : Ada_Int_Array_Type(1..Integer(Len)); begin for I in Back'Range loop Back(I) := Integer(A(I-1)); end loop; return Back; end To_Ada; begin null; end My_Pkg; Nasser -- Nasser Abbasi. C/C++/Ada Solaris. GeneAssist - A client/server application for Nucleic acid and protein sequence search and analysis. PE-Applied BioSystem division. email: nasser@apldbio.com MSEE, MSCS, MSCE, FM (and Karpov is my chess hero! ..).