Thanks @FortranFan and @sblionel for your previous answers.
Just to confirm my understanding of the mixed-language linking process, I have a question related to the following scenario.
Assume I have a C++ library in the file foo.cpp, containing a number of (public) procedures wrapped in an extern "C" scoping block. I would like to use these procedures in a Fortran program. The procedure prototypes are also declared in the file foo.h (included in foo.cpp). The file foo.h also uses a #ifdef guard to guarantee the right compiler name mangling were the header included in other C or C++ source files.
#ifdef __cplusplus
extern "C" {
#endif
void foo1(...);
void foo2(...);
int foo3(...);
#ifdef __cplusplus
}
#endif
Now to the Fortan side. The module foo_interface in file foo_interface.f90 declares interfaces for the ˙"C"˙ functions using the bind(C) attributes. Finally the fooX functions are used by a main program located in main_foo.f90.
Is a C compiler needed to arrive at an executable at all? According to my current understanding it isn’t. I just need the sequence:
g++ -I./ -c foo.cpp # include current folder for the header file
gfortran -c foo_interface.f90
gfortran -c main_foo.f90
gfortran foo.o foo_interface.o main_foo.o -lstdc++ # foo needs C++ stdlib
Essentially the linker takes care of correctly linking the C++ and Fortran binaries.
Now for a second question related to a lifetime of C descriptors.
Assume the function foo1 has the following prototype:
void foo1(void *cpp_object, const CFI_cdesc_t *fortran_array);
and has the purpose of initializing a C++ class, which stores a reference to the Fortran array. A pointer to the newly created C++ class instance is returned in *cpp_object.
Upon return from foo1, is the pointer to the C descriptor *fortran_array inside of cpp_object still a valid object? At least according to my current experience, the C descriptor seems to become corrupt in subsequent calls.
What I am trying to achieve is essentially a C++ class which “shadows” a Fortran array. Perhaps an illustration in the Fortran side should help clarify:
subroutine use_foo()
type(c_ptr) :: cpp_object = c_null_ptr
real, allocatable :: a(:,:)
allocate(a(3,1000))
call random_number(a)
! initalize cpp_object which stores reference to array a
call foo1(cpp_object,a)
! cpp_object uses array to calculate res1 and res2
call foo2(cpp_object,res1,res2)
! destroy cpp_object
call foo3(cpp_object)
! array a is deallocated automatically
end subroutine