Ada Programming/Libraries/Interfaces.C

is a unit of the Predefined Language Environment since Ada 95.

Let's see the use of this package and its children through two examples, one for C and another for C++.

Example for C
PCRE is a popular C-library that implements regular expression pattern matching using the same syntax and semantics as Perl 5. PCRE means Perl Compatible Regular Expressions. The site of this library is pcre.org

Within Gnat, there are Ada library for regular expressions : Unix-style :, and Spitbol-like :.

As an alternative, interfacing with PCRE will show some techniques for dealing with a C library. There are enough primitives inside the package to avoid a wrapper in C.

Abstract of header file pcre.h
Using version 8.02 of the file. The header file is quite long, we will just use 2 types and 4 operations, so what we need is just

Interface of the thin binding
The objective of the interface is to hide the dependency from the package Interfaces.C. and the types exposed by the interface are : Integer, String, Pcre_Type, Extra_type, (and also System.Address in the complete binding).

The types Pcre and Extra are opaque pointers and should not be accessible outside the interface so they are made private. No operation on the components of pcre_extra are necessary, so pcre and pcre_extra are just declared as System.Address.

The complete cycle in PCRE is (compile/study/exec) where Gnat.Regex has 2 phases (compile/match); the study phase is an optimization of the pattern, that output an object of type Extra. Here we by-pass the study phase.

Compile allocates and returns a pointer to the compiled pattern, that is null if some error occured. In that case, an error message is available as well as the position of the error.

Free is used to deallocate the compiled pattern.

Match takes as inputs the compiled pattern, the subject Ada string to parse. The parameter  of string is necessary in case of partial scan.

ouputs a return code (Result) that is negative if there is no match or an error. For a zero or positive return code, the match_array has the same output as the C library.

Implementation of the thin binding
In C, a string is implemented as a pointer to char terminated by a nul. Using Gnat, an Ada string is implemented with the 2 bounds first, and afterwards the content of the string.

The function

This function allocates a new copy of the data and adds a terminating null. So the data are duplicated, which can be a burden when the data weight 50 Mb.

Also to avoid a memory leak, this data must be freed after use.

The procedure Match deals with :

1/passing by reference the content of an Ada string. Due to the difference between the Ada string and the C string, the trick is to point to the first element of the Ada String. In this case, there is no terminating nul, but as we pass the length of the data, this is no trouble.

2/getting back a vector from the C code. Ada allocates this vector that is used by the C code. Therefore a  is required for the vector, as well as a  so that the Ada compiler does not interfere/optimize it.

The whole package has been tested for memory leaks with Valgrind and does not leak.

Test of Pcre binding
Example taken from Regex at the site Rosetta.org

test_0.adb
Output :

 

Complete code of the binding
The complete code of the binding and some examples can be download at sourceforge.net

Example for C++
How to use C++ functions from Ada. Please consider the following C++ code:

source file random_number.cpp
How can we call the C++ function  from an Ada program?

The solution
Start by creating an Ada specification based on the C++ header file (assuming a suitably recent GCC):

gcc -c -fdump-ada-spec random_number.h

Or read this for examples on auto-generating Ada bindings from C and C++ headers.

Comment out the  in. They are unused and they are repeated in  anyway. Save it as. (This forces C++ style Ada specs rather than C style, which is essential to link to the C++ code). Generate the Ada specification automatically:

/usr/gnat/bin/gcc -fdump-ada-spec random_number.hpp

This produces the file.

random_number_hpp.ads
While not essential, it is recommended to write a wrapper package to hide the C interface and C types, and to make the interface look like Ada:  and. (This constitutes a "thick binding", while package  is a  ). At this point you can choose what to expose to the Ada code; I have been selective (or lazy!).

random_wrapper.adb
Now write your main Ada program:

random.adb
Compile the C++ portion (more complex examples may need a Makefile):

g++ -g -m64 -c -o random_number.o random_number.cpp

Build the Ada portion:

gnatmake -m64 -gnat05 -gnato -gnatwa -fstack-check -o random random.adb -largs ./random_number.o -lstdc++

Note additional arguments  to gnatlink; extend these if you add more C++ objects and libraries.

Run it.

./random Five random numbers 9       40         2        77        66

Specification
PureC CHAR_BIT    implementation_defined SCHAR_MIN   implementation_defined SCHAR_MAX   implementation_defined UCHAR_MAX   implementation_defined int    implementation_defined  implementation_defined short  implementation_defined  implementation_defined long   implementation_defined  implementation_defined signed_char  SCHAR_MIN  SCHAR_MAX signed_char CHAR_BIT unsigned        implementation_defined unsigned_short  implementation_defined unsigned_long   implementation_defined unsigned_char  UCHAR_MAX1 unsigned_char CHAR_BIT plain_char unsigned_char ptrdiff_t  implementation_defined  implementation_defined size_t  implementation_defined C_float      implementation_defined double       implementation_defined long_double  implementation_defined char x     nul   char  implementation_defined To_C  Item   Character  char To_Ada Item  char  Character char_array  size_t     char Pack char_array char_array CHAR_BIT Is_Nul_Terminated Item  char_array  Boolean To_C  Item         String Append_Nul  Boolean  True char_array To_Ada Item      char_array Trim_Nul  Boolean  True String To_C Item        String Target      char_array Count       size_t Append_Nul  Boolean  True To_Ada Item      char_array Target    String Count     Natural Trim_Nul  Boolean  True wchar_t wide_nul  wchar_t  implementation_defined To_C  Item   Wide_Character  wchar_t To_Ada Item  wchar_t         Wide_Character wchar_array  size_t     wchar_t Pack wchar_array Is_Nul_Terminated Item  wchar_array  Boolean To_C  Item         Wide_String Append_Nul  Boolean  True wchar_array To_Ada Item      wchar_array Trim_Nul  Boolean  True Wide_String To_C Item         Wide_String Target      wchar_array Count       size_t Append_Nul   Boolean  True To_Ada Item       wchar_array Target    Wide_String Count     Natural Trim_Nul   Boolean  True char16_t x      char16_nul   char16_t  implementation_defined To_C Item  Wide_Character  char16_t To_Ada Item  char16_t  Wide_Character char16_array  size_t     char16_t Pack char16_array Is_Nul_Terminated Item  char16_array  Boolean To_C Item        Wide_String Append_Nul  Boolean  True char16_array To_Ada Item      char16_array Trim_Nul  Boolean  True Wide_String To_C Item            Wide_String Target         char16_array Count          size_t Append_Nul      Boolean  True To_Ada Item          char16_array Target       Wide_String Count        Natural Trim_Nul      Boolean  True char32_t x      char32_nul   char32_t  implementation_defined To_C Item  Wide_Wide_Character  char32_t To_Ada Item  char32_t  Wide_Wide_Character char32_array  size_t     char32_t Pack char32_array Is_Nul_Terminated Item  char32_array  Boolean To_C Item        Wide_Wide_String Append_Nul  Boolean  True char32_array To_Ada Item      char32_array Trim_Nul  Boolean  True Wide_Wide_String To_C Item            Wide_Wide_String Target         char32_array Count          size_t Append_Nul      Boolean  True To_Ada Item          char32_array Target       Wide_Wide_String Count        Natural Trim_Nul      Boolean  True Terminator_Error InterfacesC

Wikibook

 * Ada Programming/Libraries/Interfaces
 * Ada Programming/Libraries/Interfaces.C.Strings