gpt4 book ai didi

c++ - 将 Fortran 子例程链接到 C++ 程序时出错

转载 作者:行者123 更新时间:2023-11-28 02:57:35 26 4
gpt4 key购买 nike

我正在将程序从 Fortran 转换为 C++。然而,为了保持输入兼容性,我按照说明使用子例程和 Fortran 的名单功能 in this question .由于这是遗留代码,我正在处理的名单有点荒谬,有 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 header ,我已经根据 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++ 代码使用相同的 header ,您还需要一个保护,因为 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

关于c++ - 将 Fortran 子例程链接到 C++ 程序时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21631830/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com