comp.lang.ada
 help / color / mirror / Atom feed
* Calling Ada proceedures from a C program
@ 1999-05-20  0:00 Jason LaPenta
  1999-05-20  0:00 ` Gautier
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Jason LaPenta @ 1999-05-20  0:00 UTC (permalink / raw)


Hello,
    I have a linking/binding question. I'm trying to call an Ada proc.
from a C program. Something like...

extern void __test( void );  // Ada proc test in a file called test.adb
with ada defination in test.ads

int main()
{
    __test();

    return 1;
}

I'm compiling the test.ads and the main.C to object code and then trying
to link by using
gcc -o test.o main.o
The originol proc. is test (w/out the two underscores). I haven't been
able to find any examples of doing this sort of thing, so if you know of
any on the web or otherwise it would help to point me in the right
direction.

thanks
jason
lapenta@orca.ds.boeing.com






^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-05-20  0:00 Calling Ada proceedures from a C program Jason LaPenta
@ 1999-05-20  0:00 ` Gautier
  1999-05-20  0:00 ` David C. Hoos, Sr.
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Gautier @ 1999-05-20  0:00 UTC (permalink / raw)
  To: Jason LaPenta

> The originol proc. is test (w/out the two underscores). I haven't been
> able to find any examples of doing this sort of thing, so if you know of
> any on the web or otherwise it would help to point me in the right
> direction.

This is surely because the natural mixing is the reverse:
interfacing C / assembler from Ada.

Some reasons, roughly: 

- there are interfacing facilities in Ada language for C/C++, Fortran,...
- Ada has modularity, so an Ada package has a richer information
  than that you find in an .o file produced by assembler/C/C++ or any other
  macro-assembler;
- there are initialisation sequences in an Ada package;
- there are exceptions that should be able to be cascaded until the main procedure;
- you can choose the main procedure without calling it "main"

The thing you are trying to do is like interfacing C code into
a main program in assembler...

Hoping it helps...

-- 
Gautier

--------
http://members.xoom.com/gdemont/




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-05-20  0:00 Calling Ada proceedures from a C program Jason LaPenta
  1999-05-20  0:00 ` Gautier
@ 1999-05-20  0:00 ` David C. Hoos, Sr.
  1999-05-20  0:00   ` Geert Bosch
  1999-05-20  0:00 ` Compilier Im' using Jason LaPenta
  1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
  3 siblings, 1 reply; 11+ messages in thread
From: David C. Hoos, Sr. @ 1999-05-20  0:00 UTC (permalink / raw)



Jason LaPenta wrote in message <37444D8D.B6C7D7E5@orca.ds.boeing.com>...
>Hello,
>    I have a linking/binding question. I'm trying to call an Ada proc.
>from a C program. Something like...
Before anyone can help, you need to specify at least the compiler you're
using, as the procedure is compiler-dependent.







^ permalink raw reply	[flat|nested] 11+ messages in thread

* Compilier Im' using
  1999-05-20  0:00 Calling Ada proceedures from a C program Jason LaPenta
  1999-05-20  0:00 ` Gautier
  1999-05-20  0:00 ` David C. Hoos, Sr.
@ 1999-05-20  0:00 ` Jason LaPenta
  1999-05-21  0:00   ` Robert Dewar
  1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
  3 siblings, 1 reply; 11+ messages in thread
From: Jason LaPenta @ 1999-05-20  0:00 UTC (permalink / raw)


The Compilier I'm Using is  gcc and gnat
gcc version 2.8.1
GNATMAKE 3.11b

Thanks
Jason

Jason LaPenta wrote:

> Hello,
>     I have a linking/binding question. I'm trying to call an Ada proc.
> from a C program. Something like...
>
> extern void __test( void );  // Ada proc test in a file called test.adb
> with ada defination in test.ads
>
> int main()
> {
>     __test();
>
>     return 1;
> }
>
> I'm compiling the test.ads and the main.C to object code and then trying
> to link by using
> gcc -o test.o main.o
> The originol proc. is test (w/out the two underscores). I haven't been
> able to find any examples of doing this sort of thing, so if you know of
> any on the web or otherwise it would help to point me in the right
> direction.
>
> thanks
> jason
> lapenta@orca.ds.boeing.com





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-05-20  0:00 ` David C. Hoos, Sr.
@ 1999-05-20  0:00   ` Geert Bosch
  1999-05-21  0:00     ` Keith Thompson
  0 siblings, 1 reply; 11+ messages in thread
From: Geert Bosch @ 1999-05-20  0:00 UTC (permalink / raw)


"David C. Hoos, Sr." wrote:
> >I have a linking/binding question. I'm trying to call an Ada proc.
> >from a C program. Something like...
> Before anyone can help, you need to specify at least the compiler
> you're using, as the procedure is compiler-dependent.

This is not totally correct. The general mechanism, including
initialization and finalization is standardized in Ada95. Look in 
the RM for pragma Export (C, ...), "adainit", "adafinal". Annex B is 
the place to look for most of the information. On the details for
compilation commands you'd have to read your compiler's documentation.

Regards,
   Geert




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Compilier Im' using
  1999-05-20  0:00 ` Compilier Im' using Jason LaPenta
@ 1999-05-21  0:00   ` Robert Dewar
  0 siblings, 0 replies; 11+ messages in thread
From: Robert Dewar @ 1999-05-21  0:00 UTC (permalink / raw)


In article <37446AC7.98F26D1A@orca.ds.boeing.com>,
  Jason LaPenta <lapenta@orca.ds.boeing.com> wrote:
> The Compilier I'm Using is  gcc and gnat
> gcc version 2.8.1
> GNATMAKE 3.11b

Be sure to consult the secret GNAT archives (otherwise known
as the GNAT documentation) you will find useful stuff
there, some of which is directly relevant to your question!

Robert Dewar
Ada Core Technologies

P.S. I refer to them as the secret archives, because sometimes
it seems that must be secret for so many people not to have
read them :-) :-)


--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-05-20  0:00   ` Geert Bosch
@ 1999-05-21  0:00     ` Keith Thompson
  0 siblings, 0 replies; 11+ messages in thread
From: Keith Thompson @ 1999-05-21  0:00 UTC (permalink / raw)


Geert Bosch <geert@act-europe.fr> writes:
> This is not totally correct. The general mechanism, including
> initialization and finalization is standardized in Ada95. Look in 
> the RM for pragma Export (C, ...), "adainit", "adafinal". Annex B is 
> the place to look for most of the information. On the details for
> compilation commands you'd have to read your compiler's documentation.

"adainit" and "adafinal" are in B.1(39).  I mention this because they
were left out of the index.

-- 
Keith Thompson (The_Other_Keith) kst@cts.com  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center  <http://www.sdsc.edu>                 <*>
Techno-geek.  Mouse bigger than phone.  Bites heads off virtual chickens.




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
@ 1999-06-09  0:00   ` Robert Dewar
  1999-06-10  0:00   ` David Kristola
  1999-06-11  0:00   ` David C. Hoos, Sr.
  2 siblings, 0 replies; 11+ messages in thread
From: Robert Dewar @ 1999-06-09  0:00 UTC (permalink / raw)


In article <7jlsqd$khj$1@nnrp1.deja.com>,
  rekennedy@my-deja.com wrote:
> One of the things that I ran into early was getting the data
> types to match up. Finding the Interfaces.C and
> Interfaces.C.Strings packages
> provided by gnat made this task much easier.

Well I should hope these are provided by GNAT, since they are
a required part of the Ada 95 language if you provide
interfacing to C.

One thing I often notice is that people struggle to do things
which are actually quite simple, from not having done enough
homework to know all the facilities that are available.

The issue of how to interface from Ada to C is covered in a
number of Ada text books, and if the description in the RM is
not clear, then you should definitely find one of these texts.

My recommendation is to at least read annexes A and B in the
RM, these are quite readable, and describe a lot of useful
stuff (including the children of Ada mentioned in the quote
above).



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-05-20  0:00 Calling Ada proceedures from a C program Jason LaPenta
                   ` (2 preceding siblings ...)
  1999-05-20  0:00 ` Compilier Im' using Jason LaPenta
@ 1999-06-09  0:00 ` rekennedy
  1999-06-09  0:00   ` Robert Dewar
                     ` (2 more replies)
  3 siblings, 3 replies; 11+ messages in thread
From: rekennedy @ 1999-06-09  0:00 UTC (permalink / raw)


In article <37444D8D.B6C7D7E5@orca.ds.boeing.com>,
  Jason LaPenta <lapenta@orca.ds.boeing.com> wrote:
> Hello,
>     I have a linking/binding question. I'm trying to call an Ada proc.
> from a C program. Something like...
>
> extern void __test( void );  // Ada proc test in a file called
test.adb
> with ada defination in test.ads
>
> int main()
> {
>     __test();
>
>     return 1;
> }
>
> I'm compiling the test.ads and the main.C to object code and then
trying
> to link by using
> gcc -o test.o main.o
> The originol proc. is test (w/out the two underscores). I haven't been
> able to find any examples of doing this sort of thing, so if you know
of
> any on the web or otherwise it would help to point me in the right
> direction.
>
> thanks
> jason
> lapenta@orca.ds.boeing.com
>
>

I've recently been working on that same sort of thing, trying to
provide C-bindings to some Ada code that we've developed.  I'm using
the gnat95 and gcc compilers on an WinNT system to do this.  Most of
the information you need for doing this is in Appendix B of the LRM
that comes with gnat95, but some of it can be a bit difficult to find.
Hardest part is that the examples in there and in every other source
I've found only show the linkage in the other direction, Ada calling C
procedures.

To do the bindings, I ended up using pragma Export (C, my_procedure),
then defining the procedure in a header file.

I've been working on a small set of test files first, trying to figure
out the details of the linking, data passing, etc.

I've got a small ada package, named my_test_package, that is called
from a c main in a file named my_test.  Here's a copy of the steps I
use to link these:

gcc -c my_test_package.ads
gcc -c my_test_package.adb
gnatbind -n my_test_package.ali
gcc my_test.c b_my_test_package.c my_test_package.o -L. -Lc:
\gnat\bindings\win32ada\ -Lc:\gnat\lib\gcc-lib\pentium-mingw32msv\2.8.1
\adalib -lgnat

Hope that helps with your problem.

One of the things that I ran into early was getting the data types to
match up. Finding the Interfaces.C and Interfaces.C.Strings packages
provided by gnat made this task much easier.

In the test packages, I've been trying to work with a couple of
procedures and a couple of functions.
The functions accept either an integer or a string, echo the value out
to the screen, and then return the input value.  Got both of those
working, once I started using the interfaces types.

The procedures do the same thing the functions do, except the value is
returned in an out parameter. I've got it working for the integer.  It
was a bit tricky to get working, until I re-read appendix B where it
talks about how out and in/out parms are handled.  On the C-side, the
input has to be an int, but the output has to be a pointer to int.  On
the Ada side, both values are declared as int.  The compiler treats the
output as a pointer under the covers.

I'm having trouble getting the same thing to work for strings. For the
strings, I ended up using the "char_ptr" type from Interfaces.C.Strings.
On the c-side, the values are char *, on the Ada-side, they are
char_ptr.  The C calls the Ada procedure without a problem, until the
code starts to return to the C, passing the value back.  At that point,
it raises an access violation.  Still not sure what I'll have to do to
get this working. If anyone has done this, I'd really appreciate any
advice on it.

I'll list the specs, headers, etc of the files here as an example of
one way of doing this. Hopefully it will keep someone else from having
the same frustrations looking for examples.


Robert Kennedy
Science Applications International Corporation (SAIC)

my_test.c

#include "my_test_package.h"

int main()
{
  int Int_Parm_One;
  int * Int_Parm_Two;
  int Int_Parm_Three;
  int foo;
  char * String_Parm_One;
  char * String_Parm_Two;

  foo = 10;
  Int_Parm_One = 5;
  Int_Parm_Two = &foo;
  String_Parm_One = "InputVal\0";
  String_Parm_Two = "OutputVal\0";

  adainit();
  my_procedure_one(Int_Parm_One, Int_Parm_Two);
  printf ("Back from my_procedure_one, output = %d \n", *Int_Parm_Two);

  my_procedure_two(String_Parm_One, String_Parm_Two);
  printf ("Back from my_procedure_two, output = %s \n",
String_Parm_Two);

  Int_Parm_Three = my_function_one(Int_Parm_One);
  printf ("Back from my_function_one, output = %d \n", Int_Parm_Three);

  String_Parm_Two = my_function_two(String_Parm_One);
  printf ("Back from my_function_one, output = %s \n", String_Parm_Two);

  adafinal();
  return 0;
}


my_test_package.h

#ifndef __MY_TEST_PACKAGE
#define __MY_TEST_PACKAGE

extern void my_procedure_one(int Parm_One, int * Parm_Two);
extern void my_procedure_two(char * Parm_One, char * Parm_Two);
extern int my_function_one(int Parm_One);
extern char * my_function_two(char * Parm_Two);

extern void adainit();
extern void adafinal();

#endif


my_test_package.ads

with Interfaces.C;
with Interfaces.C.Strings;

package My_Test_Package is

   package Ic renames Interfaces.C;
package Ics renames Interfaces.C.Strings;
   type int_ptr is access ic.int;

-- procedure My_Procedure_One;
procedure My_Procedure_One (
      Parm_One : in Ic.Int;
      Parm_Two : out ic.int);
pragma Export(C, My_Procedure_One);

-- procedure My_Procedure_Two
procedure My_Procedure_Two(
      Parm_One : in Ics.Chars_Ptr;
      Parm_Two : out Ics.Chars_Ptr);
pragma Export(C, My_Procedure_Two);

-- function My_Function_One;
function My_Function_One (Parm_One : Ic.Int) return Ic.int;
pragma Export(C, My_Function_One);

-- function My_Function_One;
function My_Function_Two (Parm_One : Ics.Chars_Ptr)
   return Ics.Chars_Ptr;
pragma Export(C, My_Function_Two);

end My_Test_Package;


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
  1999-06-09  0:00   ` Robert Dewar
@ 1999-06-10  0:00   ` David Kristola
  1999-06-11  0:00   ` David C. Hoos, Sr.
  2 siblings, 0 replies; 11+ messages in thread
From: David Kristola @ 1999-06-10  0:00 UTC (permalink / raw)


In article 1@nnrp1.deja.com, rekennedy@my-deja.com () writes:
>I'm having trouble getting the same thing to work for strings. For the
>strings, I ended up using the "char_ptr" type from Interfaces.C.Strings.
>On the c-side, the values are char *, on the Ada-side, they are
>char_ptr.  The C calls the Ada procedure without a problem, until the
>code starts to return to the C, passing the value back.  At that point,
>it raises an access violation.  Still not sure what I'll have to do to
>get this working. If anyone has done this, I'd really appreciate any
>advice on it.
>
>I'll list the specs, headers, etc of the files here as an example of
>one way of doing this. Hopefully it will keep someone else from having
>the same frustrations looking for examples.
>
>
>Robert Kennedy
>Science Applications International Corporation (SAIC)

You did not include the body for My_Test_Package, so i am not
sure what it is doing, but the problem may be in the way out
parameters are handled.  As with the integer case, Ada may
use a pointer to the string pointer.  I am sure this is in the
documentation somewhere, but i do not have it close at hand.


--djk, keeper of arcane lore & trivial fluff
Home: David95037 at aol dot com
Spam: goto.hades@welovespam.com





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Calling Ada proceedures from a C program
  1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
  1999-06-09  0:00   ` Robert Dewar
  1999-06-10  0:00   ` David Kristola
@ 1999-06-11  0:00   ` David C. Hoos, Sr.
  2 siblings, 0 replies; 11+ messages in thread
From: David C. Hoos, Sr. @ 1999-06-11  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4480 bytes --]


rekennedy@my-deja.com wrote in message <7jlsqd$khj$1@nnrp1.deja.com>...
<large snip>

Your problem with my_procedure_two is that its prototype should be
extern void my_procedure_two(char * Parm_One, char * * Parm_Two);
instead of
extern void my_procedure_two(char * Parm_One, char * Parm_Two);

In other words, you need the added level of indirection on the
out mode parameter, just as you did for the second parameter
of my_procedure_one.

Of course, the call to my_procedure_two would be
  my_procedure_two(String_Parm_One, & String_Parm_Two);
instead of
  my_procedure_two(String_Parm_One, String_Parm_Two);

However, note that what you're doing here is allocating
memory in my_procedure_two, where the only pointer to that
memory is String_Parm_Two.  So, the following from the
Ada RM B.3.1 (58-60) is pertinent.

NOTES

58  13 New_Char_Array and New_String might be implemented either
through the allocation function from the C environment
(�malloc�) or through Ada dynamic memory allocation (�new�).
The key points are

59 � the returned value (a chars_ptr) is represented as a
     C �char *� so that it may be passed to C functions;
60 � the allocated object should be freed by the programmer
     via a call of Free, not by a called C function.

(I have no idea what is the significance of the "13" in (58)
above.)

This means, that if you wanted to be able to free the memory
so allocated, you need to do it like this:

   Ada spec:
   procedure Free (The_Memory : in out Interfaces.C.Strings.Chars_Ptr);
   pragma Export (C, Free, "Free");

   Ada body:
   procedure Free
     (The_memory : in out Interfaces.C.Strings.Chars_Ptr)
   is
   begin
       Interfaces.C.Strings.Free (The_Memory);
   end Free;

   C prototype:
   void Free (char ** the_memory);

Just a couple of small hints about your C code:

   1.  The \0 at the end of the string literals in the next
       two statements are superfluous, because string
       literals in C are automatically NUL-terminated by
       the compiler.

       String_Parm_One = "InputVal\0";
       String_Parm_Two = "OutputVal\0";

   2.  When you call my_procedure_two, the value of
       String_Parm_Two will be overwritten, thereby
       "orphaning" the memory where the string
       literal resides.


>my_test.c
>
>#include "my_test_package.h"
>
>int main()
>{
>  int Int_Parm_One;
>  int * Int_Parm_Two;
>  int Int_Parm_Three;
>  int foo;
>  char * String_Parm_One;
>  char * String_Parm_Two;
>
>  foo = 10;
>  Int_Parm_One = 5;
>  Int_Parm_Two = &foo;
>  String_Parm_One = "InputVal\0";
>  String_Parm_Two = "OutputVal\0";
>
>  adainit();
>  my_procedure_one(Int_Parm_One, Int_Parm_Two);
>  printf ("Back from my_procedure_one, output = %d \n", *Int_Parm_Two);
>
>  my_procedure_two(String_Parm_One, String_Parm_Two);
>  printf ("Back from my_procedure_two, output = %s \n",
>String_Parm_Two);
>
>  Int_Parm_Three = my_function_one(Int_Parm_One);
>  printf ("Back from my_function_one, output = %d \n", Int_Parm_Three);
>
>  String_Parm_Two = my_function_two(String_Parm_One);
>  printf ("Back from my_function_one, output = %s \n", String_Parm_Two);
>
>  adafinal();
>  return 0;
>}
>
>
>my_test_package.h
>
>#ifndef __MY_TEST_PACKAGE
>#define __MY_TEST_PACKAGE
>
>extern void my_procedure_one(int Parm_One, int * Parm_Two);
>extern void my_procedure_two(char * Parm_One, char * Parm_Two);
>extern int my_function_one(int Parm_One);
>extern char * my_function_two(char * Parm_Two);
>
>extern void adainit();
>extern void adafinal();
>
>#endif
>
>
>my_test_package.ads
>
>with Interfaces.C;
>with Interfaces.C.Strings;
>
>package My_Test_Package is
>
>   package Ic renames Interfaces.C;
>package Ics renames Interfaces.C.Strings;
>   type int_ptr is access ic.int;
>
>-- procedure My_Procedure_One;
>procedure My_Procedure_One (
>      Parm_One : in Ic.Int;
>      Parm_Two : out ic.int);
>pragma Export(C, My_Procedure_One);
>
>-- procedure My_Procedure_Two
>procedure My_Procedure_Two(
>      Parm_One : in Ics.Chars_Ptr;
>      Parm_Two : out Ics.Chars_Ptr);
>pragma Export(C, My_Procedure_Two);
>
>-- function My_Function_One;
>function My_Function_One (Parm_One : Ic.Int) return Ic.int;
>pragma Export(C, My_Function_One);
>
>-- function My_Function_One;
>function My_Function_Two (Parm_One : Ics.Chars_Ptr)
>   return Ics.Chars_Ptr;
>pragma Export(C, My_Function_Two);
>
>end My_Test_Package;
>
>
>Sent via Deja.com http://www.deja.com/
>Share what you know. Learn what you don't.







^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~1999-06-11  0:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-05-20  0:00 Calling Ada proceedures from a C program Jason LaPenta
1999-05-20  0:00 ` Gautier
1999-05-20  0:00 ` David C. Hoos, Sr.
1999-05-20  0:00   ` Geert Bosch
1999-05-21  0:00     ` Keith Thompson
1999-05-20  0:00 ` Compilier Im' using Jason LaPenta
1999-05-21  0:00   ` Robert Dewar
1999-06-09  0:00 ` Calling Ada proceedures from a C program rekennedy
1999-06-09  0:00   ` Robert Dewar
1999-06-10  0:00   ` David Kristola
1999-06-11  0:00   ` David C. Hoos, Sr.

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox