From: nasser@apldbio.com (Nasser Abbasi)
To: nasser@apldbio.com (Nasser Abbasi)
Subject: Re: on calling Ada from C/C++
Date: 1996/06/13
Date: 1996-06-13T00:00:00+00:00 [thread overview]
Message-ID: <nhn328ffe7.fsf@paralysys> (raw)
In-Reply-To: nhpw75iqsp.fsf@paralysys
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 <iostream.h>
#include <stdio.h>
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="<<i<<endl;
i = Sum(a,sizeof(a)/sizeof(int));
cout<<" in C++, first sum is "<<i<<endl;
// Now call ada to modify elements of array
Modify(a,sizeof(a)/sizeof(int));
i = Sum(a,sizeof(a)/sizeof(int));
cout<<" In C++, Ada did another sum, and the result is "<<i<<endl;
i = Sum_Version2(a,sizeof(a)/sizeof(int));
cout<<" In C++, Ada did Sum_Version2, and the result is "<<i<<endl;
adafinal();
return 0;
}
my_pkg.ads
---------
with Interfaces.C;
package My_Pkg is
package C renames Interfaces.C;
type Ada_Int_Array_type is array(Integer range <>) 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! ..).
next prev parent reply other threads:[~1996-06-13 0:00 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
1996-06-12 0:00 on calling Ada from C/C++ Nasser Abbasi
1996-06-13 0:00 ` Nasser Abbasi [this message]
1996-06-13 0:00 ` Robert Dewar
1996-06-13 0:00 ` Robert Dewar
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox