簡體   English   中英

將fortran子例程鏈接到c ++程序時出錯

[英]Error linking fortran subroutine into c++ program

我正在將程序從Fortran轉換為C ++。 但是,為了保持輸入兼容性,我按照此問題中的說明使用子例程和Fortran的名稱列表功能。 由於這是一個遺留代碼,我正在處理的名單有30多個變量更荒謬。 一切正常,直到我收到錯誤鏈接:

main.cpp:(.text+0x2732): undefined reference to `readDatainMesh(double*, int*, int*, double*, char*, double*, char*, int*, int*, int*, double*, int*, int*, int*, double*, double*, double*, int*, int*, int*, int*, double*, double*, double*, double*, int*, int*, double*, int*, int*, double*, char*, double*, double*, double*, int*, double*, double*, double*, int*, int*, int*, char*, char*, double*, double*)'

我有以下輸入文件:

readNamelists.f90:

 subroutine readDatainMesh(...) &
        bind(c, name='readDatainMesh')
        use,intrinsic :: iso_c_binding,only:c_double,c_int,c_char
        implicit none

        real(kind=c_double),    intent(inout) :: realVars
        integer(kind=c_int),    intent(inout) :: intVars
        character(kind=c_char), intent(inout) :: charVars
        .
        .
        .    

     namelist/datain_mesh/...

         open(unit = 100, file = 'input.nam', status = 'old')
         read(unit = 100, nml = datain_mesh)
         close(unit = 100)

 endsubroutine readDatainMesh 

我用gfortran -Wall -o readNamelists.o -c readNamelists.f90 這會產生關於未使用的虛擬變量的警告,但這就是全部。

我有一個函數的C頭,我已經檢查了main.cpp中的被調用函數和fortran實現。 看起來像:

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

void readDatainMesh(...);

#endif

我打電話給gcc -Wall -o main.o -c main.cpp ,它沒有發出警告。 然后最后gcc -Wall -o main main.o readNamelists.o -lstdc++ -lgfortran拋出上述錯誤。 我想也許符號不匹配所以我在兩個目標文件上運行nm並且感興趣的行是:

0000000000000000 T readDatainMesh

             U _Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_

這顯然不匹配。 我的問題是如何解決這個問題?

_Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_是包含參數類型的C ++錯位名稱。 這樣,C ++編譯器可以為重載函數提供不同的符號並區分它們。

可以從命令行中解除它:

$ echo _Z14readDatainMeshPdPiS0_S_PcS_S1_S0_S0_S0_S_S0_S0_S0_S_S_S_S0_S0_S0_S0_S_S_S_S_S0_S0_S_S0_S0_S_S1_S_S_S_S0_S_S_S_S0_S0_S0_S1_S1_S_S_ | demangle
readDatainMesh(double*, int*, int*, double*, char*, double*, char*, int*, int*, int*, double*, int*, int*, int*, double*, double*, double*, int*, int*, int*, int*, double*, double*, double*, double*, int*, int*, double*, int*, int*, double*, char*, double*, double*, double*, int*, double*, double*, double*, int*, int*, int*, char*, char*, double*, double*)

因此,您必須告訴C ++編譯器將其視為C函數而不會重載。 這可以使用extern "C"來完成。 如果從C和C ++代碼中使用相同的頭,則還需要一個保護,因為extern "C"在C中無效。

完整標題可能如下所示:

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

#ifdef  __cplusplus
extern "C" {
#endif
void readDatainMesh(...);
#ifdef  __cplusplus
}
#endif

#endif

如果你只做C ++,這是唯一可以縮短它的功能

#ifndef READNAMELISTS_H
#define READNAMELISTS_H

extern "C" void readDatainMesh(...);

#endif

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM