how to call a Fortran90 function included in a module in c++ code?

c++, fortran, fortran90, module

Solution

I am assuming you are using the g++, gfortran, mpif90 toolchain. If you have a module

module rocker
contains
subroutine bye_baby
...
end subroutine

The external C declaration for it in C++ is

extern "C"
{
    //          ,-- 2 Leading underscores to start
    //          | ,-- then the module name
    //          | |     ,-- then _MOD_
    //          | |     |    ,-- then the subroutine name
    //          V V     V    V
    extern void __rocker_MOD_bye_baby();
}

You may also need to add attribute((stdcall)) after the extern. By default, C assumes cdecl which stacks the parameters differently.

If you do not want the __rocker_MOD part, then the subroutine/function should not be declared in a module.

Problem

I m including a fortran90 program that is not mine in my C++ project . In the first stept I try to call the function by their name_() and i get the error "undefined reference to mp_mpi_cartesian_init_ "by dispalying the symbol of the obj file (using nm) i found that the function are called by their module as module_function_ so i add the module name and i Get the same problem but between fortran obj such as "Constants.f90:(.text+0x36): undefined reference to __powi4i4" here is the c++ code : ``` #include <iostream> #include <complex> using namespace std; extern"C" { void mod_save_wave_mp_read_it_psi_(int * it,complex<double>* psi_E1E2 ); void mod_mpi_cartesian_mp_mpi_cartesian_init_( ); extern int mod_mpl_h_mp_iproc_ ; } int main(){ complex<double> psi_local[512*24*512*24]; int it ; mod_mpi_cartesian_mp_mpi_cartesian_init_(); cout << "proc :" << mod_mpl_h_mp_iproc_ << "avant lecture\n"; mod_save_wave_mp_read_it_psi_(&it,psi_local); cout << "psi ="<< psi_local[0] << "poiur le proc "<<mod_mpl_h_mp_iproc_ <<"\n"; } ``` and this is an exemple of a module : ``` MODULE mod_save_wave USE mod_constants USE mod_MPI_CARTESIAN USE mod_time_mesure, ONLY : tempsEcoule USE mod_input_data, ONLY : Nt_laserPsansLaser USE mod_input_data, ONLY : n_phi, n_rho1_seg, n_rho2_seg USE mod_input_data, ONLY : Nt_periode, save_periodique !//////////////////////////////////////////////////////////////// IMPLICIT NONE ! REAL(kind=d_t) :: prog_start_time, time_max_second ! character(len=80) :: IntermedWaveDir !================================================================ CONTAINS SUBROUTINE begin_count_time() IMPLICIT NONE prog_start_time = tempsEcoule() ! END SUBROUTINE begin_count_time SUBROUTINE READ_IT_PSI( it, psi_E1E2 ) IMPLICIT NONE !//////////////////////////////////////////////////////////////////////////////// INTEGER :: it ! COMPLEX(kind=d_t), DIMENSION(n_phi,n_rho1_seg,n_phi,n_rho2_seg) :: psi_E1E2 ! !================================================================================ integer :: c do c = 0, c_max-1 if( mod(iproc,c_max)==c ) then !//////////////////////////////////////////////////////////////////////////////// OPEN( unit=11,file=concat(trim(IntermedWaveDir),concat(concat('BACK/wave_',str_iproc),'_2p2p2')),& status='old', form='unformatted', MODE='READ' ) READ(11) it ! READ(11) psi_E1E2 ! CLOSE(11) ! print*,'iproc,readed it=',iproc, it endif CALL MPI_BARRIER(MPI_COMM_WORLD,infompi) ! !================================================================================ enddo !================================================================================ END SUBROUTINE READ_IT_PSI SUBROUTINE WRITE_IT_PSI( it, psi_E1E2 ) IMPLICIT NONE !//////////////////////////////////////////////////////////////////////////////// INTEGER :: it ! COMPLEX(kind=d_t), DIMENSION(n_phi,n_rho1_seg,n_phi,n_rho2_seg) :: psi_E1E2 ! !================================================================================ integer :: c do c = 0, c_max-1 if( mod(iproc,c_max)==c ) then !//////////////////////////////////////////////////////////////////////////////// OPEN( unit=11,file=concat(trim(IntermedWaveDir),concat(concat('wave_',str_iproc),'_2p2p2')),& form='unformatted') ! WRITE(11) it+1 !---- recommence a partir de la prochaine iterat! write(11) psi_E1E2 ! CLOSE(11) ! endif CALL MPI_BARRIER(MPI_COMM_WORLD,infompi) ! !================================================================================ enddo END SUBROUTINE WRITE_IT_PSI END MODULE mod_save_wave ```

Original source