Interfacing to C from Ada95
In this tutorial I will take you through the steps of interfacing to C variables and functions. When creating bindings to libraries written in C from Ada a programmer really needs to know how to use the information contained within Appendix B of the Ada Reference Manual (ARM).
Binding variables
Firstly, I will show how to import a simple integer variable from C. Given the global variable declaration:
C code
/* A variable to import.
*/
int MyGlobal = 10;
The following Ada95 code can be used to bring it into the Ada program:
Ada95 code
-- We want to link to the C MyGlobal variable here.
My_Global : Interfaces.C.int;
pragma Import(
Convention => C,
Entity => My_Global,
External_Name => "MyGlobal");
I have used the named parameter passing mechanism so it's easier to see what's happening. We state that the linkage convention is C and the name we will give the integer in the Ada source is My_Global, we then provide the C name MyGlobal and the pragma binds the C name to the Ada name. We can then use the Ada name like this:
Ada95 code
My_Global := 25;
Binding functions
Now following from this, we can extend this knowledge to importing a simple function from C:
C code
/* A function to import.
*/
int MyAdd(int a, int b)
{
return a + b;
}
Again, using the same import pragma we can bring this function into the Ada program and make use of it:
Ada95 code
-- We now want to import a function.
function My_Add(A, B : Interfaces.C.int)
return Interfaces.C.int;
pragma Import(
Convention => C,
Entity => My_Add,
External_Name => "MyAdd");
See how the C and Ada names differ? The pragma binds the 2 together so that they can be used in a program:
Ada95 code
My_Global := My_Add(My_Global, 7);
Binding C strings
Strings in C are annoying as they can be viewed in a number of different ways. This also means that binding to them can be tricky. One way is to bind to a pointer to an array. So, for example say we have a function which returns a message string:
C code
/* A message to return to Ada.
*/
const char *Message = "This is a test string";
const char *MyString(void)
{
return Message;
}
We want to import the MyString function into the Ada program. Ada provides access to pointers to char from the Interfaces.C.Strings package:
Ada95 code
-- We have a function that returns a message in a string.
function My_String return Interfaces.C.Strings.chars_ptr;
pragma Import(
Convention => C,
Entity => My_String,
External_Name => "MyString");
-- This converts the char * array into an Ada String type.
Message : String := Interfaces.C.Strings.Value(My_String);
In the preceding code, we import as usual, but we use the chars_ptr type rather than the char_array type as we are passing a pointer and not a string from the stack. We can then transform this into an Ada String type by using the Value function.
Source code
I have placed a full example into an archive which can be built with GNAT using the following commands:
Bash code
$ tar -xzvpf importing_c.tgz
$ cd importing_c
$ make
Other Ada95 compilers will differ.
Reply #2 on : Mon September 17, 2007, 23:45:49
Reply #1 on : Sat September 15, 2007, 15:43:12
Write a comment
- Required fields are marked with *.

Reply #4 on : Mon November 19, 2007, 10:48:48