编译C++包括带有 COMMON 语句的 Fortran 库
Compiling C++ including Fortran libraries with COMMON statements
我正在编译一个需要一些库的C++程序。这些库的代码是用Fortran编写的,包含COMMON块。基本上我正在做这样的事情:
g++ -o main.cpp main lib1.a lib2.a
Lib1.a 和 lib2.a 用 Fortran 编码:
gfortran -c -o lib1.a Code1.F
gfortran -c -o lib2.a Code2.F
两者都包含一个头文件,其中包含以下内容:
double precision var1,var2
double precision var3,var4
common /block1/ var1,var2
common /block2/ var3,var4
似乎公共块出了问题。例如,更改变量在公共变量之后的顺序,或添加新变量,会导致结果随机不一致。
我知道在可能的情况下不应该使用 COMMON 语句,但我看不出在这种情况下可能有什么问题。
Fortran,它可能在变量之间插入填充。 也许Fortran和C++编译器对此存在分歧。 只是一个猜测。
如果您愿意更改 Fortran 代码,使用 ISO C 绑定会有所帮助,因为这会指示 Fortran 编译器生成与 C 编译器约定一致的代码。 http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/lin/compiler_f/bldaps_for/common/bldaps_interopc.htm 有一个常见的块示例。 基于该示例:
use, intrinsic :: iso_c_binding
real (c_double) :: var1, var2, var3, var4
common /block1/ var1, var2
common /block2/ var3, var4
bind (C) :: /block1/, /block2/
如果您愿意制作进一步的模组,更好的选择是模块变量。 然后就不用担心内存中的布局。
module global_vars
use, intrinsic :: iso_c_binding
real (c_double), bind (C) :: var1, var2, var3, var4
end module global_vars
变量在COMMON
块中的顺序很重要,更改顺序后会发生不好的事情。在使用公共块的任何地方,包括在C++程序中,它都应该是相同的。微不足道的是给这些变量命名。例如,在一个子程序中,您可以拥有:
double precision a, b
common /block1/ a, b
在另一个子例程中,您可以拥有:
double precision c, d
common /block1/ c, d
仍然a
,c
将共享相同的内存位置。这同样适用于b
和d
。这可能会导致混淆,通常的做法是将变量和公共块声明放在一个文件中,该文件由使用特定公共块的每个子例程include
-d,就像在您的情况下所做的那样。现在,如果您在任何公共块中更改某些内容,则所有子例程都将看到它已更改,并且一切都将按预期工作。
问题是你还必须改变相应的C结构,以便使其与改变的公共块对应。
例如double precision a, b
common /block1/ a, b
在 C 中对应于:
struct common_block1
{
double a;
double b;
};
extern struct common_block1 block1_;
(注意:不支持 bind(C)
属性的旧版 Fortran 编译器在每个导出标识符的末尾放置下划线,因此在 C/C++ 中,您必须将block1
引用为block1_
如果将公共块更改为:
integer a
double precision b, c
common /block1/ a, b, c
您还应该将 C 结构更改为:
struct common_block1
{
int a;
double b;
double c;
};
给定 C 和 Fortran 编译器的所有内容都使用相同的内存对齐规则。通常可以使用编译器选项 (C/C++/Fortran) 和类型属性 (C/C++) 来控制对齐方式。使用 ISO_C_BINDING
Fortran 模块可以保证在 Fortran 和 C 中使用具有相同存储大小的类型类型。建议您首先将最大的对象(例如数组、(DOUBLE) COMPLEX
变量、DOUBLE PRECISION
变量等)放在公共块的开头,然后是较小的对象等。
我明白了这个错误的起源。我首先编译了库lib1.a,包括头文件。然后我实际上修改了这个头文件(尤其是公共块)并编译了库lib2.a。这似乎合乎逻辑,在不同库中的两个公共块之间引起混乱......
我会详细检查这一点,但我很确定这是解释。感谢您的建议,它帮助我检查了一切,这就是我找到解决方案的方式!
- 我的简单if-else语句是如何无法访问的代码
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 为什么是0;C++中的有效语句
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 我似乎对if/else的基本语句有问题:/
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- If语句在c++中被忽略
- 比较if语句中的数组值和int值
- 以在Qt中的IF语句中设置时间延迟
- Craps游戏问题,忽略if语句
- "类模板示例<int>;"语句对 C++11 是什么意思?
- FORTRAN 中的维度语句
- 编译C++包括带有 COMMON 语句的 Fortran 库
- Fortran 的参数语句是否与 C/C++ 的 #define 语句相似?