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=0.7 required=5.0 tests=BAYES_00,MSGID_RANDY autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,4e101bd1b1b0a66c X-Google-Attributes: gid103376,public From: rekennedy@my-deja.com Subject: Re: Calling Ada proceedures from a C program Date: 1999/06/09 Message-ID: <7jlsqd$khj$1@nnrp1.deja.com> X-Deja-AN: 487485825 References: <37444D8D.B6C7D7E5@orca.ds.boeing.com> X-Http-Proxy: 1.1 x26.deja.com:80 (Squid/1.1.22) for client 136.205.149.133 Organization: Deja.com - Share what you know. Learn what you don't. X-Article-Creation-Date: Wed Jun 09 14:13:45 1999 GMT Newsgroups: comp.lang.ada X-Http-User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT) Date: 1999-06-09T00:00:00+00:00 List-Id: In article <37444D8D.B6C7D7E5@orca.ds.boeing.com>, 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 > > 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.