C++ 调用Fortran函数,从C++;
我有一堆旧的F77源代码(通常使用C++ 调用Fortran函数,从C++;,c++,fortran,g++,gfortran,mixed-programming,C++,Fortran,G++,Gfortran,Mixed Programming,我有一堆旧的F77源代码(通常使用gfortran-std=legacy在x86_64上编译)。 它在形式上包含许多函数: 双复函数f(x,y,i) 双精度x,y 整数i f=cmplx(x,y)*i 返回 结束 我需要从一些C++代码中调用这些函数(通常是在 x8664 64 < /COD>中使用 g++< /COD> >)。 它使用默认的FortranKIND=8: extern“C”{std::complex f_(double*x,double*y,int*i);} 当我使用-fr
gfortran-std=legacy
在x86_64
上编译)。
它在形式上包含许多函数:
双复函数f(x,y,i)
双精度x,y
整数i
f=cmplx(x,y)*i
返回
结束
我需要从一些C++代码中调用这些函数(通常是在<代码> x8664 64 < /COD>中使用<代码> g++< /COD> >)。
KIND=8
:
extern“C”{std::complex f_(double*x,double*y,int*i);}
-freal-8-real-4
选项强制使用默认FortranKIND=4
时,它会起作用:
extern“C”{std::complex f_(float*x,float*y,int*i);}
extern“C”{uuuuuu complex128 f_uuu(uuu float128*x,uuu float128*y,int*i)}
令我惊讶的是,在本例中,它似乎也适用于(返回值位于*z
):
extern“C”{void f_u(uuu complex128*z,uuu float128*x,uuu float128*y,int*i)}
以上两个原型中哪一个是(更多?)合适的
-freal-8-real-10
选项使用所需的默认FortranKIND=10
。在FORTRAN内部,<代码>类<代码> >代码>精度<代码>,<代码>范围<代码> >代码> sieOS/<代码>返回值,它直接对应于C++ <代码>长双< /代码>。所以,我试着:
extern“C”{std::复数f_(长双精度*x,长双精度*y,int*i);}
外部“C”{void f_uz(std::complex*z,long double*x,long double*y,int*i)}
extern“C”{void f_(长双精度*x,长双精度*y,int*i,std::complex*z);}
但我根本无法让它工作
也许需要添加一些特殊的标志到<代码> gfortran < /COD>和/或<代码> G++< /Corp>调用,以便让C++检索FORTRAN <代码> Type=10 < /COD>复杂值 注意:我认为我不能使用
-ff2c
<强>更新(2020.0804)< /强>:我已经能够欺骗C++编译器,以便它似乎为任何fortran <代码> Orth= 4,8,10< /代码生成适当的代码。诀窍是在C++中使用ISO C99 <代码>复数< /COD>(注:此技巧仅适用于<代码>类=10 < /COD>,但它实际上适用于<代码>类型=4,8< /代码>:
#包括
#定义C99KIND long double/*它可以是“float”、“double”或“long double”*/
外部“C”{C99KIND_复形f_(C99KIND*x,C99KIND*y,int*i);}
<>请注意,在C++中,不能使用例如<代码>长双复数< /C> >但幸运的是,代码> long double double复合体仍然很好。
<> C++中的ISO999代码>复杂的< /代码>的可用性相当有限。例如,使用-std=c++11
(或更新版本),即使是最基本的creal*
和cimag*
函数也会消失
<> >最好的办法是立即将返回的值复制到一些标准的C++模板复变量中,例如使用(如:<代码> fy< <代码>返回>代码> c99类复合体< /代码>):
std::complex 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
#包括
#包括
#包括
长双复数f(长双复数,长双复数,int);
int
主(空)
{
int i;
长双x,y;
长双复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);
返回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
%cat a.f90
双复函数f(x,y,i)
隐式无
双精度::x,y
整数i
f=cmplx(x,y)*i!cmplx我的不是你所期望的
端函数f
%b.c.类
#包括
#包括
#包括
长双复数f_2;(长双*,长双*,int*);
int
主(空)
{
int i;
长双x,y;
长双复z;
i=42;
x=1;
y=2;
printf(“%.10Lf%.10Lf\n”,x,y);
z=f_z(&x,&y,&i);
x=creall(z);
y=cimagl(z);
printf(“%.10Lf%.10Lf\n”,x,y);
返回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
还是去参加三足鼎立吧。下面是C++代码,与第二个例子中的文件A.F90一起使用。
#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”{std::复数f_10;(长双精度*,长双精度*,int*);}
int main()
{
std::复z;
长双x,y;
int i;
i=42;
x=1;
y=2;
z=f_z(&x,&y,&i);
std::我想问题是,即使80位FPU计算可能用于长双精度
,sizeof(长双精度)
,因此存储布局与Fortran的不匹配。不知道是否有任何开关将长双精度
存储为10字节。为什么希望种类=10?但实现这一点的方法不是随机选取种类和编译器标志,而是FortranYes定义的标准方法,sizeof(长双精度)在C++中,为16,但FORTRAN返回的值为<代码>实数(类型=10)< /代码>。