comp.lang.ada
 help / color / mirror / Atom feed
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! ..).




  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