Calling C++ from C and Fortran

16 minute read

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