comp.lang.ada
 help / color / mirror / Atom feed
From: nasser@apldbio.com (Nasser Abbasi)
Subject: on calling Ada from C/C++
Date: 1996/06/12
Date: 1996-06-12T00:00:00+00:00	[thread overview]
Message-ID: <nhpw75iqsp.fsf@paralysys> (raw)



this is fyi:

This is a little note about calling Ada subprogram from C++ .

I started 2-3 hours ago to learn how to call Ada from C++, I still
need to learn more about this. But it turned out much easier than I
as I thought it would be. The main issues are on how
to declare the Ada subprograms in C++, and how to make sure the way
the Ada subprogram is called matches the way it expects to be
called.

A C++ main calls an Ada procedure to update an integer. (I also
use C in this example just for testing.)

I also show the steps used to build the program, and few points at the end
about few things.

This was done on solaris 2.5, using gnat 3.04.

file main.cc
-------------
#include <iostream.h>
#include <stdio.h>

extern "C" { void Ada_Function(int*); 
             void adainit();  // this and adafinal are calls to ada
             void adafinal(); // rtl to insure things are initialized
           }                  // and finailized ok...

main()
{
 int i=0;

 adainit();   // call befor any other ada call

 printf("This is a  C printf ... \n");
 cout<<"this is C++ cout..."<<endl;

 cout<<" before calling Ada, i="<<i<<endl;

 Ada_Function(&i);  

 cout<<" after calling Ada, i="<<i<<endl;

 adafinal();  // call before program terminates

 return 0;

}

file: ada_function.adb
----------------------
with Text_Io; use Text_Io;
procedure Ada_Function(I:in out integer) is
begin
   Put_Line("This is Ada Put_Line ...");
   Put_Line("Number passed in is" & Integer'Image(I));
   I := I+1;
end;
pragma Export(C,Ada_Function,"Ada_Function");



Steps used to build main* are : (note: gcc here is the gcc that comes
with gnat 3.04. for the g++ include files, and libg++.a and
libstdc++.a libraries, those were obtained seperatly and build in different
directory. I found out for example that  cc1plus* was needed to be under
 2.7.2/ directory in the gnat 2.4 solaris installtion tree, but it was not, 
so I copied that file from the 2.7.2/ directory under the tree that was build
seperatly for the 2.5 solaris. This way I was able to use gnat gcc to build
C++, without cc1plus* one can not build C++ files using the gcc that comes
with gnat 3.04-solaris 2.4.)


gcc -c main.cc -I/usr/local/netshare/lib/g++-include
gnatbind -n ada_function.ali
gnatlink -L/usr/local/netshare/lib ada_function.ali main.o \
          -lg++ -lstdc++ -o main

...now run the program...

{95} main
This is a  C printf ... 
this is C++ cout...
 before calling Ada, i=0
This is Ada Put_Line ...
Number passed in is 0
 after calling Ada, i=1


few points I noticed:
1) In C++, one must declare the Ada procedure and functions as
   C functions, else C++ will mangle the ada function names, and the
   gnatlink step will fail as poor linker will not be able to resolve
   the name.  for example, if one do not use extern "C" {..}, and
   then look at the object file generated, one sees :
   $ nm -x main.o

main.o:

[Index]   Value      Size      Type  Bind  Other Shndx   Name
[5]     |0x00000000|0x00000000|NOTY |GLOB |0x0  |UNDEF  |Ada_Function__Fi

   But after using the extern "C" {...} to declare the Ada procedure,
   the function name is not changed by C++ :
   $nm -x main.o

main.o:

[Index]   Value      Size      Type  Bind  Other Shndx   Name
[14]    |0x00000000|0x00000000|NOTY |GLOB |0x0  |UNDEF  |Ada_Function

   Now, the function name matches that in the ada object file, and
   the linker is a happy camper.


2) In the Ada procedure, defining Ada_function as
   procedure Ada_Function(I:in out integer) 
                            ^^^^^
   or
   procedure Ada_Function(I:out integer)
                            ^^^^

   resulted in no difference in build or run results. 

3) more about point 2: How to make sure that the way the Ada 
   subprogram is called from the C++ module matches that the way 
   Ada subprogram is defined in the Ada module?

   For example, in the above example, in main.cc, one can change the 
   argument being passed to the Ada procedure from int* to char*, and rebuild
   the C++ main.cc, link to the ada procedure, and no errors are
   detected,  untill the program is run.

   So, it is important to "manually" make sure the way the Ada program 
   is called matches the way it is defined. Is there better way? ..

   When calling C++ from C++, one uses common function prototypes (in
   common headers) to make sure all modules agree on the function 
   signature, so that the way a function is called matches the way the is 
   defined. Similar idea is used when calling Ada from Ada. The Ada
   compiler makes sure the formal and actual parameters agree.

   But how to insure this when calling Ada from C++ ?

Nasser

==========================================================
Nasser Abbasi. Senior software engineer. C/C++/Solaris. 
GeneAssist- a client/server application for Nucleic acid 
and protein sequence search and analysis.
PE-Applied BioSystem division.        nasser@apldbio.com   


-- 
Nasser Abbasi. Senior software engineer. C/C++/Solaris. 
GeneAssist- a client/server application for Nucleic acid 
and protein sequence search and analysis.
PE-Applied BioSystem division.        nasser@apldbio.com   

 





             reply	other threads:[~1996-06-12  0:00 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-06-12  0:00 Nasser Abbasi [this message]
1996-06-13  0:00 ` on calling Ada from C/C++ Nasser Abbasi
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