[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

29. Generating Ada Bindings for C and C++ headers

GNAT now comes with a binding generator for C and C++ headers which is intended to do 95% of the tedious work of generating Ada specs from C or C++ header files.

Note that this capability is not intended to generate 100% correct Ada specs, and will is some cases require manual adjustments, although it can often be used out of the box in practice.

Some of the known limitations include:

The code generated is using the Ada 2005 syntax, which makes it easier to interface with other languages than previous versions of Ada.

29.1 Running the binding generator  
29.2 Generating bindings for C++ headers  
29.3 Switches  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

29.1 Running the binding generator

The binding generator is part of the gcc compiler and can be invoked via the `-fdump-ada-spec' switch, which will generate Ada spec files for the header files specified on the command line, and all header files needed by these files transitively. For example:

 
$ g++ -c -fdump-ada-spec -C /usr/include/time.h
$ gcc -c -gnat05 *.ads

will generate, under GNU/Linux, the following files: `time_h.ads', `bits_time_h.ads', `stddef_h.ads', `bits_types_h.ads' which correspond to the files `/usr/include/time.h', `/usr/include/bits/time.h', etc..., and will then compile in Ada 2005 mode these Ada specs.

The -C switch tells gcc to extract comments from headers, and will attempt to generate corresponding Ada comments.

If you want to generate a single Ada file and not the transitive closure, you can use instead the `-fdump-ada-spec-slim' switch.

You can optionally specify a parent unit, of which all generated units will be children, using -fada-spec-parent=unit.

Note that we recommend when possible to use the g++ driver to generate bindings, even for most C headers, since this will in general generate better Ada specs. For generating bindings for C++ headers, it is mandatory to use the g++ command, or gcc -x c++ which is equivalent in this case. If g++ cannot work on your C headers because of incompatibilities between C and C++, then you can fallback to gcc instead.

For an example of better bindings generated from the C++ front-end, the name of the parameters (when available) are actually ignored by the C front-end. Consider the following C header:

 
extern void foo (int variable);

with the C front-end, variable is ignored, and the above is handled as:

 
extern void foo (int);

generating a generic:

 
procedure foo (param1 : int);

with the C++ front-end, the name is available, and we generate:

 
procedure foo (variable : int);

In some cases, the generated bindings will be more complete or more meaningful when defining some macros, which you can do via the `-D' switch. This is for example the case with `Xlib.h' under GNU/Linux:

 
g++ -c -fdump-ada-spec -DXLIB_ILLEGAL_ACCESS -C /usr/include/X11/Xlib.h

The above will generate more complete bindings than a straight call without the `-DXLIB_ILLEGAL_ACCESS' switch.

In other cases, it is not possible to parse a header file in a stand-alone manner, because other include files need to be included first. In this case, the solution is to create a small header file including the needed #include and possible #define directives. For example, to generate Ada bindings for `readline/readline.h', you need to first include `stdio.h', so you can create a file with the following two lines in e.g. `readline1.h':

 
#include <stdio.h>
#include <readline/readline.h>

and then generate Ada bindings from this file:

 
$ g++ -c -fdump-ada-spec readline1.h


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

29.2 Generating bindings for C++ headers

Generating bindings for C++ headers is done using the same options, always with the g++ compiler.

In this mode, C++ classes will be mapped to Ada tagged types, constructors will be mapped using the CPP_Constructor pragma, and when possible, multiple inheritance of abstract classes will be mapped to Ada interfaces (See section `Interfacing to C++' in GNAT Reference Manual, for additional information on interfacing to C++).

For example, given the following C++ header file:

 
class Carnivore {
public:
   virtual int Number_Of_Teeth () = 0;
};

class Domestic {
public:
   virtual void Set_Owner (char* Name) = 0;
};

class Animal {
public:
  int Age_Count;
  virtual void Set_Age (int New_Age);
};

class Dog : Animal, Carnivore, Domestic {
 public:
  int  Tooth_Count;
  char *Owner;

  virtual int  Number_Of_Teeth ();
  virtual void Set_Owner (char* Name);

  Dog();
};

The corresponding Ada code is generated:

 
  package Class_Carnivore is
    type Carnivore is limited interface;
    pragma Import (CPP, Carnivore);

    function Number_Of_Teeth (this : access Carnivore) return int is abstract;
  end;
  use Class_Carnivore;

  package Class_Domestic is
    type Domestic is limited interface;
    pragma Import (CPP, Domestic);

    procedure Set_Owner
      (this : access Domestic;
       Name : Interfaces.C.Strings.chars_ptr) is abstract;
  end;
  use Class_Domestic;

  package Class_Animal is
    type Animal is tagged limited record
      Age_Count : aliased int;
    end record;
    pragma Import (CPP, Animal);

    procedure Set_Age (this : access Animal; New_Age : int);
    pragma Import (CPP, Set_Age, "_ZN6Animal7Set_AgeEi");
  end;
  use Class_Animal;

  package Class_Dog is
    type Dog is new Animal and Carnivore and Domestic with record
      Tooth_Count : aliased int;
      Owner : Interfaces.C.Strings.chars_ptr;
    end record;
    pragma Import (CPP, Dog);

    function Number_Of_Teeth (this : access Dog) return int;
    pragma Import (CPP, Number_Of_Teeth, "_ZN3Dog15Number_Of_TeethEv");

    procedure Set_Owner
      (this : access Dog; Name : Interfaces.C.Strings.chars_ptr);
    pragma Import (CPP, Set_Owner, "_ZN3Dog9Set_OwnerEPc");

    function New_Dog return Dog;
    pragma CPP_Constructor (New_Dog);
    pragma Import (CPP, New_Dog, "_ZN3DogC1Ev");
  end;
  use Class_Dog;


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

29.3 Switches

`-fdump-ada-spec'
Generate Ada spec files for the given header files transitively (including all header files that these headers depend upon).

`-fdump-ada-spec-slim'
Generate Ada spec files for the header files specified on the command line only.

`-fada-spec-parent=unit'
Specifies that all files generated by `-fdump-ada-spec*' are to be child units of the specified parent unit.

`-C'
Extract comments from headers and generate Ada comments in the Ada spec files.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by GNAT Mailserver on June, 30 2014 using texi2html