Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Calling C++ from FORTRAN

Sandeep_J_
Beginner
1,073 Views

I had read a topic of calling C++ from FORTRAN.

Basically, I need to access C++ class data from FORTRAN- when calling C++ from FORTRAN.

Steve suggested in one of his post to use access routines (get, put, etc.) if you need to communicate class data between the languages (

http://software.intel.com/en-us/forums/topic/296424)

.

Please can anyone advise what exactly you eman by access routines?

0 Kudos
8 Replies
Sandeep_J_
Beginner
1,073 Views

I had read a topic of calling C++ from FORTRAN.

Basically, I need to access C++ class data from FORTRAN- when calling C++ from FORTRAN.

Steve suggested in one of his post to use access routines (get, put, etc.) if you need to communicate class data between the languages (

http://software.intel.com/en-us/forums/topic/296424)

.

Please can anyone advise what exactly you eman by access routines?

0 Kudos
Steven_L_Intel1
Employee
1,073 Views

What I mean is: instead of trying to read and write the C++ variables directly from Fortran, write functions in C++ that return the value of a specific variable and, if necessary, functions to set the value of a variable. You can call these from Fortran and it spares you a lot of C+++ messiness.

0 Kudos
Sandeep_J_
Beginner
1,073 Views

Thanks Steve-However, I'm not evr clear.

1) I have a FORTRAN routine MyFORTRANRoutine()

2) I have a cpp routine MYCPPRoutine_A which is a member of a class (sat MyClass_A). So, I cannot call it from FORTRAN (Right?- or let us say it is not easyto do that)

3) You say write functions in C++ that return the values of specific variable. I did not get that. Should these functions be public members of class MyClass_A ?

Can you jsut put it in form of step 1, step 2, step 3- what exactly you meant?

0 Kudos
Steven_L_Intel1
Employee
1,073 Views

No, I can't really put it that way. You need to write 'extern "C"' routines in your C++ source that are callable from Fortran. These routines would then get or set the variables. They would not be members of classes, but separate routines. I am not a C++ expert so I don't know all the details.

0 Kudos
mecej4
Honored Contributor III
1,073 Views

Sandeep: You can, conceptually at least, do what Steve suggested in two steps:

1. Write code in C (not C++) to access the C++ object components. Make sure that the components are the usual built-in C types for which Fortran has equivalents. Test the code out and confirm that it works.

2. Convert the access functions that you wrote in Step 1 to Fortran, either using C-interoperability features or using older mixed-language programming techniques.

0 Kudos
Steven_L_Intel1
Employee
1,073 Views

I was not suggesting step 2 - indeed one may not be able to do that. What I had in mind was writing C++ routines that accessed the class, but was coded as an 'extern "C"' routine so that it had C calling compatibility, that took arguments or returned values interoperable with Fortran. These routines could then easily be called from the Fortran code using the C interoperability features.

0 Kudos
Sandeep_J_
Beginner
1,073 Views

Did you mean this Steve:

call MY_CPPRoutine(chars,ok,cancel,xx)  (from FORTRAN)

C++ code

extern "C "void MY_CPPRoutine (char[],bool*,bool*,double*);

class CRectangle

 {

int x, y;

int area () {return(x*y);}

 

public:

double k;

void set_values (int,int,double*);

   

};

void CRectangle::set_values (inta,intb,double* k)

{

double m;

  x = a;

  y = b;

  *k=area();

}

void MY_CPPRoutine(char chars[],bool*ok,bool*cancel,double*k)

{

CRectangle rect;

double m;

bool ok1,cancel1;

ok1=true;

cancel1=false;

*ok=ok1;

*cancel=cancel1;

strcpy(chars,"blah");

m=0;

rect.set_values (3,4,k);

  }

 

0 Kudos
IanH
Honored Contributor III
1,073 Views

An example that I think is along the lines of what is being discussed:

[cpp]//------------------------------------------------------------------------------
// Our C++ class.

class my_class
{
private:
  int private_data;
 
public:
  my_class(int new_data)
  {
    private_data = new_data;
  }
 
  int get_data() const
  {
    return private_data;
  }
 
  void set_data(int new_data)
  {
    private_data = new_data;
  }
};

//------------------------------------------------------------------------------
// Accessor functions for Fortran to call.

// Wrapper for my_class::get_data.
extern "C" int my_class_get_data(my_class* object_ptr)
{
  return object_ptr->get_data();
}

// Wrapper for my_class::set_data.
extern "C" void my_class_set_data(my_class* object_ptr, int new_data)
{
  object_ptr->set_data(new_data);
}

// Constructs a new my_class object on the heap.
extern "C" my_class* my_class_new(int new_data)
{
  return new my_class(new_data);
}

// Frees a my_class object previously created with my_class_new.
extern "C" void my_class_delete(my_class* object_ptr)
{
  delete object_ptr;
}
[/cpp]

[fortran]PROGRAM UseMyClass

  USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT
  IMPLICIT NONE

  INTERFACE
    FUNCTION get_data(object_ptr) BIND(C, NAME='my_class_get_data')
      USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT
      IMPLICIT NONE
      TYPE(C_PTR), INTENT(IN), VALUE :: object_ptr
      INTEGER(C_INT) :: get_data
    END FUNCTION get_data
    SUBROUTINE set_data(object_ptr, new_data) BIND(C, NAME='my_class_set_data')
      USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT
      IMPLICIT NONE
      TYPE(C_PTR), INTENT(IN), VALUE :: object_ptr
      INTEGER(C_INT), INTENT(IN), VALUE :: new_data
    END SUBROUTINE set_data
    FUNCTION new(new_data) BIND(C, NAME='my_class_new')
      USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT
      IMPLICIT NONE
      INTEGER(C_INT), INTENT(IN), VALUE :: new_data
      TYPE(C_PTR) :: new
    END FUNCTION new
    SUBROUTINE delete(object_ptr) BIND(C, NAME='my_class_delete')
      USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
      IMPLICIT NONE
      TYPE(C_PTR), INTENT(IN), VALUE :: object_ptr
    END SUBROUTINE delete
  END INTERFACE

  TYPE(C_PTR) :: object_ptr
 
  !*****************************************************************************
 
  object_ptr = new(1_C_INT)
  PRINT "('get_data says:',I0)", get_data(object_ptr)
 
  CALL set_data(object_ptr, 2_C_INT)
  PRINT "('get_data says:',I0)", get_data(object_ptr)
 
  CALL delete(object_ptr)
 
END PROGRAM UseMyClass
[/fortran]

The use of bare pointers in C++, and to a lesser extent, bare C_PTR's on the Fortran side, are things that I'd consider avoiding or wrapping, from a code robustness point of view, but that might start to obscure the example.

0 Kudos
Reply