Как вызвать функцию Fortran90, включенную в модуль в коде C ++?

Я включил программу fortran90, которая не моя, в мой проект C ++.

В первом шаге я пытаюсь вызвать функцию по их name_ () и получаю сообщение об ошибке «неопределенная ссылка на mp_mpi_cartesian_init_», отображая символ файла obj (используя nm). Я обнаружил, что функция вызывается их модулем как module_function_ поэтому я добавляю имя модуля и получаю ту же проблему, но между fortran obj, например, «Constants.f90 :(. text + 0x36): неопределенная ссылка на __powi4i4»

Вот код C ++:

 #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";
}

и это пример модуля:

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_timeSUBROUTINE 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_PSISUBROUTINE 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_PSIEND MODULE mod_save_wave

5

Решение

Я предполагаю, что вы используете набор инструментов g ++, gfortran, mpif90. Если у вас есть модуль

module rocker
contains
subroutine bye_baby
...
end subroutine

Внешнее объявление C для него в C ++:

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();
}

Вам также может понадобиться добавить атрибут((stdcall)) после экстерьера. По умолчанию C предполагает использование cdecl, который по-разному складывает параметры.

Если вам не нужна часть __rocker_MOD, то подпрограмма / функция не должна быть объявлена ​​в модуле.

5

Другие решения

Прежде всего, на Фортране я настоятельно рекомендую использовать возможности C-привязок в Fortran 2003, и особенно iso_c_binding модуль. Вы можете увидеть много примеров для этого на SO, среди других эта почта. Затем вы избавляетесь от проблемы «как мой компилятор фортрана называет мои процедуры» прозрачным и независимым от компилятора способом.

Проблема с линковкой возникает, когда вам не хватает некоторых библиотек вашего компилятора Фортрана. Вы можете либо попытаться связать свой объектный файл с помощью компилятора Фортрана, либо выяснить, какой библиотеки не хватает, и связать ее вручную. Некоторые компиляторы Fortran также имеют опции для создания библиотеки с автоматическим связыванием библиотек, связанных с компилятором.

1

По вопросам рекламы [email protected]