7

私のC++プロジェクトには私のものではないfortran90プログラムが含まれています。

最初のステップで、name_()で関数を呼び出そうとすると、objファイルのシンボルを(nmを使用して)表示せずに「mp_mpi_cartesian_init_への未定義の参照」というエラーが発生します。関数がモジュールによってmodule_function_として呼び出されていることがわかりました。したがって、モジュール名を追加すると、同じ問題が発生しますが、「Constants.f90:(。text + 0x36):undefined referenceto__powi4i4」などのFortranobj間で発生します。

これが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_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
4

2 に答える 2

6

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

externの後に属性((stdcall))を追加する必要がある場合もあります。デフォルトでは、Cはパラメーターを異なる方法でスタックするcdeclを想定しています。

__rocker_MOD部分が必要ない場合は、サブルーチン/関数をモジュールで宣言しないでください。

于 2013-03-23T12:09:47.670 に答える
1

まず、Fortran側では、CバインディングのFortran 2003機能、特にiso_c_bindingモジュールを使用することを強くお勧めします。SO、特にこの投稿でそのための多くの例を見ることができます。次に、透過的でコンパイラに依存しない方法で、「Fortranコンパイラが私のプロシージャにどのように名前を付けるか」の問題を取り除きます。

私が推測するFortranコンパイラのいくつかのライブラリが欠落しているため、リンクの問題が発生します。Fortranコンパイラを使用してオブジェクトファイルをリンクするか、不足しているライブラリを見つけて手動でリンクすることができます。一部のFortranコンパイラーには、コンパイラー関連ライブラリーの自動リンクを使用してライブラリーを作成するためのオプションもあります。

于 2013-03-22T06:55:32.590 に答える