Reputation: 11
I'm trying to insert a C++ layer between two Fortran subroutines. I also need to pass as argument a derived type that I don't want to declare in C++, since I don't neet to access to its data, and it is in my original program a complex type, using in turn a lot of other types.
I made a simple Fortran program:
module my_module
implicit none
type :: my_type
real :: x
end type my_type
end module my_module
subroutine fortran_subroutine(b)
use my_module
implicit none
type(my_type), pointer, intent(in) :: b
print *, b%x
end subroutine fortran_subroutine
program test
use my_module
implicit none
abstract interface
subroutine sub (b)
import :: my_type
type(my_type), pointer, intent(in) :: b
end subroutine sub
end interface
type(my_type), pointer :: a
procedure (sub), pointer :: f_ptr => null ()
procedure (sub) :: fortran_subroutine
allocate(a)
a%x = 1.0
f_ptr => fortran_subroutine
call c_plus_plus_layer(f_ptr,a)
end program
And here is the C++ intermediate layer:
extern "C"
{
void c_plus_plus_layer_(void (*pointer_to_fortran_function)(void **), void ** x);
}
// Intermediate layer of C++ designed to launch a Fortran subroutine
void c_plus_plus_layer_(void (*pointer_to_fortran_function)(void **), void ** x)
{
pointer_to_fortran_function(x);
}
However, I get an error when reaching the print
instruction when compiling with the Intel compilers (v13), as I lost the data stored within my derived type somewhere in the C++ layer.
The gcc and gfortran compilers do not return anything.
May I ask for your help ?
Upvotes: 1
Views: 157
Reputation: 59999
Fortran 2003 has a new way of interfacing with C. The module iso_c_binding
declares a derived type type(c_ptr)
that represents void*
and the attribute value
which lets you to pass the pointer by value. It also contains procedures c_loc()
and c_f_pointer()
for conversion of Fortran and C pointers.
For procedure pointers, similarly type(c_funptr)
, and procedures c_funloc()
and c_f_procptr()
are available.
Study a lot of questions and answers here in tag fortran-iso-c-binding
Also, by using the bind(C)
attribute, you get similar effects es extern(C)
in C++ and you do not have to worry about name mangling and the trailing_
. The bind(C)
attribute is important to achieve the true C
behavior of the Fortran procedure, e.g., the value
attribute.
Note that if you use bind(C)
the compiler will often warn you or even raise an error that Fortran pointer
attribute cannot be used in such a procedure, because C wouldn't understand it.
Upvotes: 5