Table of Contents

The Problem

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

header file random_number.h

#ifndef GUARD_random_number_h
#define GUARD_random_number_h
#include <unistd.h>
#include <ctime>
#include <cstdlib>
void getNewSeed();
double getRandom(int a, int b);
int getRandomInt(int a, int b); 
int getRounded(double res);

source file random_number.cpp

#include <unistd.h>
#include <ctime>
#include <cstdlib>
#include "random_number.h"
#include <math.h>
using std::srand;
using std::rand;
void getNewSeed() {
double getRandom(int a, int b) {
       return (b-a) * ( (double) rand()/RAND_MAX) + a;
int getRounded(double res) {
       return (res > 0.0) ? floor(res + 0.5) : ceil(res - 0.5);
int getRandomInt(int a, int b) {
       res = getRandom(a, b);
       return getRounded(res);

How can we call the C++ function getRandomInt(0,10) 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 #includes in random_number.h. They are unused and they are repeated in random_number.cpp anyway. Save it as random_number.hpp. (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

with Interfaces.C; use Interfaces.C;
package random_number_hpp is
  procedure getNewSeed;  
  -- random_number.hpp:8:21 
  pragma Import (CPP, getNewSeed, "_Z14getNewSeedv");
  function getRandom (a : int; b : int) return double;
  --  random_number.hpp:9:35
  pragma Import (CPP, getRandom, "_Z14getRandomii");
  function getRandomInt (a : int; b : int) return int;
  --  random_number.hpp:10:39
  pragma Import (CPP, getRandomInt, "_Z21getRandomIntii");
  function getRounded (res : double) return int;
  -- random_number.hpp:11:26
  pragma Import (CPP, getRounded, "_Z10getRoundedd");
end random_number_hpp;

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 random_wrapper.adb. (This constitutes a “thick binding”, while package random_number_h is a thin binding). At this point you can choose what to expose to the Ada code; I have been selective (or lazy!).

package random_wrapper is
  procedure initialise_seed;
  function random_between(a,b : in Integer) return Integer;
end random_wrapper;


with random_number_hpp;
use random_number_hpp;
with Interfaces.C;
use Interfaces.C;
package body random_wrapper is
  procedure initialise_seed is
  end initialise_seed;
  function random_between(a,b : in Integer) return Integer is begin
     return Integer(getRandomInt (int(a), int(b)));
  end random_between;
end random_wrapper;

Now write your main Ada program:


--  Random number tester
with Ada.Text_Io;               use Ada.Text_Io;
with Ada.Integer_Text_Io;       use Ada.Integer_Text_Io; with random_wrapper;
use random_wrapper;
procedure random is
  Put("Five random numbers");
  for i in 1 .. 5 loop
  end loop;
end random;

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 -largs ./random_number.o -lstdc++ to gnatlink; extend these if you add more C++ objects and libraries.

Run it.

Five random numbers


This page was adapted from a post under the subject Need some light on using Ada or not in comp.lang.ada. The question was put forward by Luis P. Mendes and kindly answered by Brian Drummond.