- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一堆旧的 F77 源代码(通常在 x86_64
和 gfortran -std=legacy
上编译)。它在形式上包含了相当多的功能:
double complex function f(x, y, i)
double precision x, y
integer i
f = cmplx(x, y) * i
return
end
我需要从一些 C++ 代码调用这些函数(通常在 x86_64
和 g++
上编译)。
它使用默认的 Fortran KIND=8
:
extern "C" { std::complex<double> f_(double *x, double *y, int *i); }
当我强制执行默认的 Fortran KIND=4
时它起作用了使用 -freal-8-real-4
选项:
extern "C" { std::complex<float> f_(float *x, float *y, int *i); }
当我强制执行默认的 Fortran KIND=16
时它起作用了使用 -freal-8-real-16
选项(在 C++ 中为 #include <quadmath.h>
):
extern "C" { __complex128 f_(__float128 *x, __float128 *y, int *i); }
令我惊讶的是,在这种情况下,它似乎也适用于(返回值在 *z
中):
extern "C" { void f_(__complex128 *z, __float128 *x, __float128 *y, int *i); }
以上两个原型(prototype)中哪个是(更多?)合适的?
我的问题是我无法让它与我想要的默认 Fortran 一起工作 KIND=10
使用 -freal-8-real-10
选项。在 Fortran 内部,kind
, precision
, range
和 sizeof
直接对应于 C++ long double
的返回值.所以,我尝试了:
extern "C" { std::complex<long double> f_(long double *x, long double *y, int *i); }
extern "C" { void f_(std::complex<long double> *z, long double *x, long double *y, int *i); }
extern "C" { void f_(long double *x, long double *y, int *i, std::complex<long double> *z); }
但我根本无法让它工作。
也许我需要为 gfortran
添加一些特殊标志和/或 g++
调用以使 C++ 检索 Fortran KIND=10
复杂的值(value)?注意:我认为我不能使用 -ff2c
.
更新(2020.08.04):我已经能够欺骗 C++ 编译器,使其似乎为任何 Fortran 生成正确的代码 KIND=4,8,10
.诀窍是使用 ISO C99 _Complex
在 C++ 中(注意:此技巧仅对 KIND=10
是必需的,但它实际上也适用于 KIND=4,8
):
#include <complex.h>
#define C99KIND long double /* it can be "float", "double" or "long double" */
extern "C" { C99KIND _Complex f_(C99KIND *x, C99KIND *y, int *i); }
请注意,在 C++ 中,您不能使用例如long double complex
不过还好long double _Complex
还是可以的。
ISO C99 的可用性 _Complex
在 C++ 中是相当有限的。例如,使用 -std=c++11
(或更新)甚至是最基本的 creal*
和 cimag*
功能消失。
因此,最好的办法是立即将返回值复制到一些标准的 C++ 模板化复杂变量中,例如使用类似的东西(注意:f_
返回 C99KIND _Complex
):
std::complex<C99KIND> z = f_(&x, &y, &i);
最佳答案
如果您想正确完成这项工作,请学习如何实际使用 Fortran 的种类类型参数并将您的 Fortran 代码正确移植到 REAL(10)
。是的,我知道 10
不可移植;然而,我们正在讨论特定的 Fortran 处理器。
考虑一下,
function f(x, y, i) result(r) bind(c, name='f')
use iso_c_binding, only : ep => c_long_double
implicit none
complex(ep) r
real(ep), intent(in), value :: x, y
integer, intent(in), value :: i
r = cmplx(x, y, ep) * i
end function f
而且,由于我不使用 C++,但您应该能够根据需要更新 C
#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
long double complex f(long double, long double, int);
int
main(void)
{
int i;
long double x, y;
long double complex z;
i = 42;
x = 1;
y = 2;
printf("%.10Lf %.10Lf\n", x, y);
z = f(x, y, i);
x = creall(z);
y = cimagl(z);
printf("%.10Lf %.10Lf\n", x, y);
return 0;
}
% gfortran -c a.f90
% gcc -o z b.c a.o -lm
% ./z
1.0000000000 2.0000000000
42.0000000000 84.0000000000
OP 声明他不会为他/她的 Fortran 代码的正确移植而烦恼,因此,必须使用编译器选项来神奇地(是的,这很神奇)进行移植。这是一个例子
% cat a.f90
double complex function f(x, y, i)
implicit none
double precision :: x, y
integer i
f = cmplx(x, y) * i ! cmplx my not do what you expect
end function f
% cat b.c
#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
long double complex f_(long double *, long double *, int *);
int
main(void)
{
int i;
long double x, y;
long double complex z;
i = 42;
x = 1;
y = 2;
printf("%.10Lf %.10Lf\n", x, y);
z = f_(&x, &y, &i);
x = creall(z);
y = cimagl(z);
printf("%.10Lf %.10Lf\n", x, y);
return 0;
}
% gfcx -c -freal-8-real-10 a.f90
% gcc -o z b.c a.o -lm
% ./z
1.0000000000 2.0000000000
42.0000000000 84.0000000000
不妨选择三重奏。下面是第二个示例中与上述文件 a.f90 一起使用的 C++ 代码。
#include <iostream>
#include <complex>
#include <cmath>
extern "C" { std::complex<long double> f_(long double *, long double *, int *); }
int main()
{
std::complex<long double> z;
long double x, y;
int i;
i = 42;
x = 1;
y = 2;
z = f_(&x, &y, &i);
std::cout << z << '\n';
}
关于c++ - 调用从 C++ 返回 KIND=10 复数值的 Fortran 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63230415/
是的,我知道..,这不是想象的...这是一个真正的 Fortran 问题。 以前的版本是指 Fortran 2003、95、90,甚至 77。 我所说的“向后兼容”是指可以轻松运行为 2008 年以前
我有一个程序,它的变量中有一个值。一旦确定了该值,我想调用另一个程序并使用该变量的值来确定在新程序中的位置。有人知道该怎么做吗? 最佳答案 如果您有 Fortran 2008 编译器,您将拥有标准子例
namelist 是一种有用的 fortran 结构,可以从文件中快速初始化变量。 namelist 有一个名称并包含一组具有已知类型的变量。这使得它类似于 type 结构。 通常情况下,给程序或子例
我正在遍历索引,我正在检查我是否不在第一个循环交互和另一个条件中。如果第一个条件是 .False.,我不想评估第二个条件。 do i = 1, n if ( i /= 1 .and. var(
Fortran 2003 具有用于数组连接的方括号语法,Intel fortran 编译器也支持它。我在这里为矩阵连接写了一个简单的代码: program matrix implicit none r
我正在尝试通过重载类型名称来制作自定义数据类型构造函数。但是,在进行调用时,将调用默认构造函数。我不明白我做错了什么。 这是有问题的代码片段。 module test type, pu
我的最终目标是在 Fortran 中有一个通用的映射函数,即一个接受任意类型 A 的数组和一个 A->B 类型的函数的函数,将此函数应用于给定数组的所有元素并返回一个B 类型的数组。我无法用数组实现它
我正在学习 Fortran,在使用格式编写时发现了一些奇怪的东西(我使用的是 Fortran onlinegdb) Program Hello real, dimension(3,2):: array
Fortran 中的INTERFACE 语句是否使其成为正式实现multiple dispatch 的编程语言? ? (我问是因为所链接的维基百科文章在其看似全面的支持相关范式的示例编程语言列表中并未
我可以使用 Fortran 95 编译器编译 Fortran 90 文件吗? Fortran 95 似乎有很多,但 Fortran 90 没有。 最佳答案 这个可以: NAGWare f95 Comp
嗨,我在 Fortran 中对二维离散化问题强加边界条件时遇到了麻烦。我的离散化网格是一个二维正方形,在 x,y 方向上从 -L 到 L。 我想强加这样的边界条件, 在 x=L 的边界线上,指定了函数
Fortran 是否有与 C assert 等效的标准函数/关键字? ? 我找不到 assert我在Fortran2003标准中提到过。我发现了一些如何使用预处理器的方法,但是在这个 answer建议
我有一系列的作业,使用“;”将它们分配给同一个ike。分开statemnts,但我收到此错误: 1.0;磅(1,9) 1个 错误:(1)处无法分类的陈述 在文件LJ.F90:223中 如果每个语句都在
我正在使用 gfortran -std=f2008。我有一个函数,它返回一个包含可分配数组的派生类型。该函数在返回之前调用allocate()。似乎在分配数组的函数返回之后,数组会自动释放一段时间,并
我制作了这个小型测试程序来“证明”在编译之前(或者如果你让它们可分配),你不能在不指定它们的大小的情况下使用向量。我的观点失败了。我期待本地向量“num”会失败。程序在执行程序之前无法知道它的大小。大
出于优化原因,Fortran 强制子例程或函数的虚拟参数不是别名,即它们不指向相同的内存位置。 我想知道相同的约束是否适用于函数的返回值。 换句话说,对于给定的 myfunc 函数: function
我已经在Fortran 90中编写了一个相当大的程序。它已经运行了一段时间了,但是今天我尝试将其提高一个档次并增加问题的大小(这是研究非标准的有限元求解器,如果那样的话)。可以帮助任何人...)现在,
在 C 和 C++ 中,有许多操作会导致未定义的行为,即允许编译器做任何它想做的事情的情况。 Examples包括在释放变量后使用它,释放变量两次和取消引用空指针。 Fortran 是否也有未定义的行
通常我使用fortran进行数值分析,然后使用matlab、R和python进行后期和前期工作。 我发现 matlab、R 和 python 在终端中提供了命令提示符,以便您可以运行脚本以及从命令行立
在 Fortran 中将变量设置为 +Infinity 的最安全方法是什么?目前我正在使用: program test implicit none print *,infinity() con
我是一名优秀的程序员,十分优秀!