Skip navigation
NASA Logo, National Aeronautics and Space Administration
Modeling Guru Banner
Currently Being Moderated

C++ Calls in Fortran

VERSION 2  Click to view document history
Created on: Jul 31, 2017 11:47 AM by Jules Kouatchou - Last Modified:  Jul 31, 2017 12:56 PM by Jules Kouatchou

There are three main steps to follow in order to be able to call call C++ routines in a Fortran program :

 

  1. Create a C++ class with the associated routines.
  2. Create C wrapper interfaces to C++ routines
  3. Create the Fortran wrapper interfaces to C routines

 

To read details on how to implement the above steps, consult the references below.

 

We show an example where C++ objects are manipulated in a Fortran program.

 

C++ Code for the C++ Class and the C Interfaces (pointrectangle_class.cc)

#include <iostream>

using namespace std;

struct Point {
  double x;
  double y;
};

struct Rectangle {
  Point corner;
  double width;
  double height;
};

class pointrectangle {

    Rectangle r;

  public:
    pointrectangle (Rectangle);

    Point findCenter ()
    {
      double x = r.corner.x + r.width/2;
      double y = r.corner.y + r.height/2;
      Point result = {x, y};
      return result;
    }

    double findArea ()
    {
       return (r.width*r.height);
    }

    void printInfo()
    {
       Point center = findCenter();
       cout << "Center Point coordinates: " << endl;
       cout << "    x-value: " << center.x << endl;
       cout << "    y-value: " << center.y << endl;
       cout << "The area is: " << findArea() << endl;
    }
};

//------------------------------
// Constructor of pointrectangle
//------------------------------

pointrectangle::pointrectangle (Rectangle box) {
  r.corner.x = box.corner.x;
  r.corner.y = box.corner.y;
  r.width    = box.width;
  r.height   = box.height;
}

//-------------------------------------
// C wrapper interfaces to C++ routines 
//-------------------------------------

extern "C" {
  pointrectangle *pointrectangle__new (Rectangle a) {
    return new pointrectangle(a);
  }

  Point pointrectangle__findCenter (pointrectangle *This) {
    return This->findCenter();
  }

  double  pointrectangle__findArea (pointrectangle *This) {
    return This->findArea();
  }

  void  pointrectangle__printInfo (pointrectangle *This) {
    return This->printInfo();
  }

  void pointrectangle__delete (pointrectangle *This) {
    delete This;
  }
}

//-------------------------------
// Example main() written in C++:
//-------------------------------
/*
int main () {
  Rectangle mybox = { {10.0, 0.0}, 100, 200 };
  pointrectangle rect( mybox );

  rect.printInfo();

  return 0;
}
*/

 

 

Fortran Code for C Wrapper Interfaces (pointrectangle_module.f90)



module pointrectangle_module




use, intrinsic :: ISO_C_Binding, only: C_int, C_double


use, intrinsic :: ISO_C_Binding, only: C_ptr, C_NULL_ptr




implicit none




private




TYPE, BIND(C) :: fPoint


REAL(C_double) :: x


REAL(C_double) :: y


END TYPE fPoint




TYPE, BIND(C) :: fRectangle


TYPE(fPoint) :: corner


REAL(C_double) :: width


REAL(C_double) :: height


END TYPE fRectangle





type pointrectangle_type


private


type(C_ptr) :: object = C_NULL_ptr


end type pointrectangle_type




!------------------------


! C function declarations


!------------------------


interface


function C_pointrectangle__new (a) result(this) bind(C,name="pointrectangle__new")


import


type(C_ptr) :: this


TYPE(fRectangle), value :: a


end function C_pointrectangle__new




subroutine C_pointrectangle__delete (this) bind(C,name="pointrectangle__delete")


import


type(C_ptr), value :: this


end subroutine C_pointrectangle__delete




function C_pointrectangle__findCenter (this) result(center) bind(C,name="pointrectangle__findCenter")


import


TYPE(fPoint) :: center


type(C_ptr), value :: this


end function C_pointrectangle__findCenter




function C_pointrectangle__findArea (this) result(area) bind(C,name="pointrectangle__findArea")


import


REAL(C_double) :: area


type(C_ptr), value :: this


end function C_pointrectangle__findArea




subroutine C_pointrectangle__printInfo (this) bind(C,name="pointrectangle__printInfo")


import


type(C_ptr), value :: this


end subroutine C_pointrectangle__printInfo




end interface




interface new


module procedure pointrectangle__new


end interface new




interface delete


module procedure pointrectangle__delete


end interface delete




interface findArea


module procedure pointrectangle__findArea


end interface findArea




interface printInfo


module procedure pointrectangle__printInfo


end interface printInfo




interface findCenter


module procedure pointrectangle__findCenter


end interface findCenter




public :: new, delete, findCenter, findArea, printInfo


public :: pointrectangle_type, fPoint, fRectangle

!------------------------------------------------------------------------------


CONTAINS

!------------------------------------------------------------------------------

      !-------------------------------------------------
      ! Fortran wrapper routines to interface C wrappers
      !-------------------------------------------------
      subroutine pointrectangle__new(this,a)
          type(pointrectangle_type), intent(out) :: this
          TYPE(fRectangle) :: a
          this%object = C_pointrectangle__new(a)
      end subroutine pointrectangle__new

      subroutine pointrectangle__delete(this)
          type(pointrectangle_type), intent(inout) :: this
          call C_pointrectangle__delete(this%object)
          this%object = C_NULL_ptr
      end subroutine pointrectangle__delete

      subroutine pointrectangle__printInfo(this)
          type(pointrectangle_type), intent(in) :: this
          call C_pointrectangle__printInfo(this%object)
      end subroutine pointrectangle__printInfo

      function pointrectangle__findCenter(this) result(center)
          type(pointrectangle_type), intent(in) :: this
          TYPE(fPoint) :: center
          center = C_pointrectangle__findCenter(this%object)
      end function pointrectangle__findCenter

      function pointrectangle__findArea(this) result(area)
          type(pointrectangle_type), intent(in) :: this
          REAL(C_double) :: area
          area = C_pointrectangle__findArea(this%object)
      end function pointrectangle__findArea
!------------------------------------------------------------------------------
      end module pointrectangle_module

 

 

Main Fortran Program (pointrectangle_main.f90)



program pointrectangle_main




use pointrectangle_module




type(pointrectangle_type) :: rect


type(fPoint)          
:: center


type(fRectangle)      
:: mybox


double precision      
:: area




mybox%corner%x  = 10.0d0


mybox%corner%y  =  0.0d0


mybox%width 
= 100.0d0


mybox%height
= 200.0d0




call new(rect, mybox)




center = findCenter(rect)


area   = findArea(rect)




write(*,*) '-------------------------------------'


write(*,*) 'Print out from C++'


write(*,*) '-------------------------------------'


call printInfo(rect)




write(*,*) '-------------------------------------'


write(*,*) 'Print out from Fortran'


write(*,*) '-------------------------------------'


write(*,*) '
Center Point x: ', center%x


write(*,*) '
Center Point y: ', center%y


write(*,*) '
Area:       
', area




call delete(rect)




end program pointrectangle_main

 

 

Compilation Steps

 

g++ -c pointrectangle_class.cc
gfortran -c pointrectangle_module.f90
gfortran -c pointrectangle_main.f90
gfortran -o pointrectangle.ex pointrectangle_class.o pointrectangle_module.o pointrectangle_main.o -lstdc++

 

 

References

  1. Fortran and Cpp objects
  2. Calling C++ from C and Fortran
  3. Mixing Code in C, C++ and Fortran
Comments (0)
USAGov logo NASA Logo - nasa.gov