Calling C++ from C and Fortran


All the code in this article is available as a gist, if you want to use it.

The number of available languages nowadays is very big, and growing every day. As a library writer, I would like to make sure that all the cool code I write today will still be runnable in 10 or 20 years, if it is still useful. Ideally, this very good library (let’s call it libfoo) would be language agnostic, such that any programmer can use it, whatever his favorite language be.

Picking a language to write a library

In real world, I will always need to write some glue code between languages. In order to make it easier to write this glue code, I can use C to write my library. Any existing language does has a C interface, and can call C code in one way or another.

But I don’t really like C. I find that for my particular library, an object-oriented (OO) language will help me, and will allow me to be more efficient. So, I need an OO language with a very straightforward C interface. This interface will then be called by all the bindings. And here comes the C++ !

As usual, when writing a C++ library, we should start by writing down our main interface specification, in an header file. This library will be the Foo library, built around the following Foo.hpp file:

#include <string>

class Foo {
public:
    Foo(int a, int b);
    ~Foo();

    int bar(int c) const;
    double baz(double d) const;
private:
    int a;
    int b;
};

void foo_speaker(std::string s);

This is the most boring library ever, with only one class, two useless function member and a global function. The library implementation can be found in the corresponding Foo.cpp file:

#include "Foo.hpp"
#include <iostream>
using namespace std;


Foo::Foo(int _a, int _b): a(_a), b(_b){
    cout << "C++ side, constructor" << endl;
}

Foo::~Foo(){
    cout << "C++ side, destructor" << endl;
}

int Foo::bar(int c) const{
    return a + c;
}

double Foo::baz(double d) const{
    return d + b;
}

void foo_speaker(string s){
    Foo f(4, 2);
    cout << s << " Foo(4, 2).bar(3) is: " <<  f.bar(3) << endl;
}

Creating the C API for our code

The good thing with C++, is its very straightforward C interface. All we have to do is use an extern "C" statement around the functions we need to wrap. So let’s create a mixed C/C++ header containing the exported C interface to libfoo.

We will wrap all the public functions, together with the constructor and the destructor. The foo.h file contains the C interface, and can be parsed by either a C compiler or a C++ compiler.

#ifdef __cplusplus // Are we compiling this with a C++ compiler ?
extern "C" {
    class Foo;
    typedef Foo FOO;
#else
    // From the C side, we use an opaque pointer.
    typedef struct FOO FOO;
#endif

// Constructor
FOO* create_foo(int a, int b);

// Destructor
void delete_foo(FOO* foo);

// The const qualificators maps from the member function to pointers to the
// class instances.
int foo_bar(const FOO* foo, int c);
double foo_baz(const FOO* foo, double d);

void foo_speaker(const char* s);

#ifdef __cplusplus
}
#endif

This C wrapper will be implemented in C++. All we need is to use a pointer to our Foo class, creating it dynamically with new. So let’s put this code to the foo_capi.cpp file.

#include "foo.h"
#include "Foo.hpp"

#include <iostream>
using namespace std;

FOO* create_foo(int a, int b){
    cout << "C API, create_foo" << endl;
    return new Foo(a, b);
}

void delete_foo(FOO* foo){
    cout << "C API, delete_foo" << endl;
    delete foo;
}

int foo_bar(const FOO* foo, int c){
    return foo->bar(c);
}

double foo_baz(const FOO* foo, double d){
    return foo->baz(d);
}

void foo_speaker(const char* s) {
    foo_speaker(string(s));
}

Wrapping the C API to Fortran

Why fortran ? Why this old and dying language ? You may ask. Well, three reasons here: first, Fortran is still very used in the high performance computing (HPC) world. You know, these guys running calculations for days on thousand of processor. And this is not a metaphor: super-computers frequently have at least 1024 processor per computing node. Second, the last standard is from 2008, and the previous one in 2003 introduced object-oriented programming. And third, I like this language, because it is as simple as C for simple tasks, but a lot more safer and easier to use.

I’ll split the fortran interface in two file, because wrapping C can become very verbose. The first one is foo_cdef.f90, and contains the interface declaration for the external C function. This is the equivalent of the foo.h file.

! C functions declaration
interface
    function create_foo_c(a, b) bind(C, name="create_foo")
        use iso_c_binding
        implicit none
        type(c_ptr) :: create_foo_c
        integer(c_int), value :: a
        integer(c_int), value :: b
    end function

    subroutine delete_foo_c(foo) bind(C, name="delete_foo")
        use iso_c_binding
        implicit none
        type(c_ptr), value :: foo
    end subroutine

    function foo_bar_c(foo, c) bind(C, name="foo_bar")
        use iso_c_binding
        implicit none
        integer(c_int) :: foo_bar_c
        ! The const qualification is translated into an intent(in)
        type(c_ptr), intent(in), value :: foo
        integer(c_int), value :: c
    end function

    function foo_baz_c(foo, c) bind(C, name="foo_baz")
        use iso_c_binding
        implicit none
        real(c_double) :: foo_baz_c
        type(c_ptr), intent(in), value :: foo
        real(c_double), value :: c
    end function

    ! void functions maps to subroutines
    subroutine foo_speaker_c(str) bind(C, name="foo_speaker")
        use iso_c_binding
        implicit none
        character(len=1, kind=C_CHAR), intent(in) :: str(*)
    end subroutine
end interface

What is interesting here ? We use the iso_c_binding module from fortran 2003, and bind the function to their C name. Another point is the value attribute for all the parameter: in Fortran, all the arguments are passed by reference, so we have to precise that we will use the pass-by-value convention.

And that’s all we need to have something functional ! But let’s make this interface feels a bit more like fortran code. For this, we will use the object-oriented (OO) capacities of the Fortran 2003 standard. Their is something funny in wrapping C++ OO code to plain old C to build and OO module in fortran … All this code goes to the foo_mod.f90 file:

module libfoo
    use iso_c_binding

    private
    public :: foo, foo_speaker

    ! Yes, include is a keyword in Fortran !
    include "foo_cdef.f90"

    ! We'll use a Fortan type to represent a C++ class here, in an opaque maner
    type foo
        private
        type(c_ptr) :: ptr ! pointer to the Foo class
    contains
        ! We can bind some functions to this type, allowing for a cleaner syntax.
        final :: delete_foo ! Destructor
        procedure :: delete => delete_foo_polymorph ! Destructor for gfortran
        ! Function member
        procedure :: bar => foo_bar
        procedure :: baz => foo_baz
    end type

    ! This function will act as the constructor for foo type
    interface foo
        procedure create_foo
    end interface

contains ! Implementation of the functions. We just wrap the C function here.
    function create_foo(a, b)
        implicit none
        type(foo) :: create_foo
        integer, intent(in) :: a, b
        create_foo%ptr = create_foo_c(a, b)
    end function

    subroutine delete_foo(this)
        implicit none
        type(foo) :: this
        call delete_foo_c(this%ptr)
    end subroutine

    ! Bounds procedure needs to take a polymorphic (class) argument
    subroutine delete_foo_polymorph(this)
        implicit none
        class(foo) :: this
        call delete_foo_c(this%ptr)
    end subroutine

    integer function foo_bar(this, c)
        implicit none
        class(foo), intent(in) :: this
        integer, intent(in) :: c
        foo_bar = foo_bar_c(this%ptr, c)
    end function

    double precision function foo_baz(this, c)
        implicit none
        class(foo), intent(in) :: this
        double precision, intent(in) :: c
        foo_baz = foo_baz_c(this%ptr, c)
    end function

    subroutine foo_speaker(str)
        implicit none
        character(len=*), intent(in) :: str
        character(len=1, kind=C_CHAR) :: c_str(len_trim(str) + 1)
        integer :: N, i

        ! Converting Fortran string to C string
        N = len_trim(str)
        do i = 1, N
            c_str(i) = str(i:i)
        end do
        c_str(N + 1) = C_NULL_CHAR

        call foo_speaker_c(c_str)
    end subroutine
end module

This library can now be used in a fortran program! As you can see, the library interface is really easy to use, and looks a lot like the C++ interface.

program test
    use libfoo
    implicit none
    type(foo) :: f

    ! Create an object of type foo
    f = foo(3, 4)

    ! Call bound procedures (member functions)
    write(*,*) f%bar(60), " should be ", 63
    write(*,*) f%baz(10d0), " should be ", 14.0d0

    call foo_speaker("From Fortran!")

    ! The destructor should be called automatically here, but this is not yet
    ! implemented in gfortran. So let's do it manually.
#ifdef __GNUC__
    call f%delete
#endif
end program

Theoretically, the destructor should be automatically called when a variable goes out of scope, enabling the RAII idiom in Fortran, but the gfortran implementation (as of 4.9.2) is not complete for this point.

We can now compile the code, using this Makefile:

FC = gfortran
CXX = g++

UNAME := $(shell uname -s)

FCFLAGS = -Wall -Wextra
CCFLAGS = -Wall -Wextra
ifeq ($(UNAME_S),Darwin)
	LDFLAGS = -lstdc++
else
	LDFLAGS = -lc++
endif

all: test.x
test.o : foo_mod.o

%.x : %.o foo_mod.o foo_capi.o Foo.o
	${FC} $^ -o $@ ${LDFLAGS}

%.o : %.f90
	${FC} ${FCFLAGS} -c $< -o $@

%.o : %.cpp
	${CXX} ${CCFLAGS} -c $^ -o $@

.PHONY : clean

clean :
	${RM} -rf *.o *.mod test.x

You should note that as gfortran is the program which will call the linker, we have to explicitly link to the C++ standard library. And now we can run our program!

$ make
$ ./test.x
C API, create_foo
C++ side, constructor
          63  should be           63
   14.000000000000000       should be    14.000000000000000
C++ side, constructor
From Fortran! Foo(4, 2).bar(3) is: 7
C++ side, destructor
C API, delete_foo
C++ side, destructor

So, what is missing for this interface? We should add a couple of try/cacth statements in the CAPI implementation, and replace it by a status code, in order to play nicely with the C++ exceptions. Another amelioration point is for the foo_cdef.f90 and foo_mod.f90 files, which are rather repetitive, boring and error prone to write. It should be possible to use a C parser to generate these files from the foo.h file. This would make another article!