如何正确链接gfortran和gcc?
我试图编写一个C函数来调用一段fortran代码。我认为直接链接fortran代码比将fortran重写为C更容易。我在mac上使用gcc/g++/gfortran,直接下载并安装了二进制文件 fortran代码位于。我要调用的特定子例程是如何正确链接gfortran和gcc?,c,gcc,compiler-errors,fortran,gfortran,C,Gcc,Compiler Errors,Fortran,Gfortran,我试图编写一个C函数来调用一段fortran代码。我认为直接链接fortran代码比将fortran重写为C更容易。我在mac上使用gcc/g++/gfortran,直接下载并安装了二进制文件 fortran代码位于。我要调用的特定子例程是子例程igrf12syn(isv、date、itype、alt、colat、elong、x、y、z、f) 我编写的包装器如下所示: #include <stdio.h> extern void igrf12syn( int *isv, dou
子例程igrf12syn(isv、date、itype、alt、colat、elong、x、y、z、f)
我编写的包装器如下所示:
#include <stdio.h>
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
double *colat, double *elong, double* x,double* y, double* z, double* f );
int main(){
double B[4], BabsDervs[3], BrDervs[3], BthDervs[3], BphDervs[3];
double r, th, ph,year,alt2,lat,colat,elong,x,y,z,f;
int isv;
// igrf12syn (isv,date,itype,alt,colat,elong,x,y,z,f)
r = 6371e3;
th = 0.57;
ph = 0;
year = 2015;
alt2 = 200.0;
lat = 33.25;
colat = 90.0-lat;
elong = 0.0;
isv =1;
igrf12syn_(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
printf("%0.4e",f);
return 0;
}
我得到的错误是:
duplicate symbol _main in:
testigrf.o
igrf12.o
ld: 1 duplicate symbol for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [igrf] Error 1
我理解此错误的含义,我可以为.o
文件生成nm
文件,该文件显示了主功能。但是,我不知道如何更改Fortran代码以消除此错误
因此,我的问题如下:
1.如何更改Fortran或C代码来解决此问题?特别是,由于fortran代码以程序IGRF开始
我是否正确调用igrf12syn
例程?我担心我的称呼不对。我也可能在传递变量方面做得很差,这必须通过引用来完成
谢谢你的帮助,如果我调用这些例程真的很愚蠢,请告诉我。我调用Fortran例程已经很久了,但是你的工作看起来似乎是合理的
现在编写一个简短的fortran子例程,在独立文件中编译,通过引用子例程参数测试调用
subroutine igrf12syn (isv,date,itype,alt,colat,elong,x,y,z,f)
当然,您可以尝试编译fortran文件,只需删除程序行,直到子例程定义为止。从我看来,它看起来是独立的,但编译器在检查源代码方面会做得更好。首先,你的C程序testigrf.C
有缺陷。事实上,,
你得到了警告:
testigrf.c: In function ‘main’:
testigrf.c:23:5: warning: implicit declaration of function ‘igrf12syn_’ [-Wimplicit-function-declaration]
igrf12syn_(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
这是因为您已经声明了一个名为igrf12syn
的函数并调用了
其中一个名为igrf12syn\uu
,编译器对此一无所知
将igrf12syn更改为igrf12syn,重新编译,然后显示的错误为:
testigrf.c: In function ‘main’:
testigrf.c:23:26: warning: passing argument 3 of ‘igrf12syn’ from incompatible pointer type [-Wincompatible-pointer-types]
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
testigrf.c:3:14: note: expected ‘double *’ but argument is of type ‘int *’
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
^
testigrf.c:23:44: error: incompatible type for argument 7 of ‘igrf12syn’
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
testigrf.c:3:14: note: expected ‘double *’ but argument is of type ‘double’
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
^
testigrf.c:23:46: error: incompatible type for argument 8 of ‘igrf12syn’
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
testigrf.c:3:14: note: expected ‘double *’ but argument is of type ‘double’
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
^
testigrf.c:23:48: error: incompatible type for argument 9 of ‘igrf12syn’
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
testigrf.c:3:14: note: expected ‘double *’ but argument is of type ‘double’
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
^
testigrf.c:23:50: error: incompatible type for argument 10 of ‘igrf12syn’
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
^
testigrf.c:3:14: note: expected ‘double *’ but argument is of type ‘double’
extern void igrf12syn( int *isv, double *year, double *itype, double *alt,
^
在继续之前,请阅读诊断并修复错误。他们
例如,可以通过更改以下内容来修复:
double r, th, ph,year,alt2,lat,colat,elong,x,y,z,f;
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
到
和改变:
double r, th, ph,year,alt2,lat,colat,elong,x,y,z,f;
igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);
致:
这将使编译器满意,尽管它可能无法表达您的意图,
我不清楚
您知道不能将两个程序链接到一个程序中,
因为链接器将发现重复的main
函数。你需要链接
C主程序只需使用Fortran子程序igrf12syn
接下来,下载并保存文件https://www.ngdc.noaa.gov/IAGA/vmod/igrf12.f
。
在文本/编程编辑器中打开它。选择所有行-完成
组成子例程igrf12syn的行,包括前导空格,来自:
subroutine igrf12syn (isv,date,itype,alt,colat,elong,x,y,z,f)
致:
将此选择完全保存为复制到中的新文件igrf12syn.f
与testigrf.c
相同的目录
然后,在该目录中打开控制台并执行以下命令:
$ gcc -c -o testigrf.o testigrf.c
$ gfortran -fno-underscoring -c -o igrf12syn.o igrf12syn.f
$ gfortran -o testigrf testigrf.o igrf12syn.o
它们将编译并链接您的程序,作为同一目录中的testigrf
最后,重复前两个命令,每个命令都带有附加选项-Wall
,
查看您尚未意识到的警告。考虑修复程序
删除警告,因为它们很可能意味着程序不会
照你所期望的去做。始终在gcc/g++/gfortran
编译器中包含-Wall
编译时对你有任何重要的代码。没有语言C/C++,只有两种不同的语言C和C++!您的代码看起来像C。请勿发布链接。问题必须是独立的。另外请注意,您的问题包含离题问题,内容过于广泛且缺乏信息。阅读。该链接已发布,因为我认为不值得将所有代码复制到该帖子中。igrf12.f
属于公共领域。我会理解C 3和C++是两种不同的语言。但是您可以使用g++和适当的头来编译C代码。不,您不能。您可以使用一个公共子集,它比您想象的要小。然而,告诉你不同的是,至少不知道他们中有谁写得比“Hello world”好得多。相同的语法并不意味着相同的语义。谢谢迈克,这个答案基本上是正确的。在发帖之前,我应该想一想,努力一点。我要注意的是,我在shell命令中使用了以下命令,并且效果良好:gcc-lgfortran-c testigrf.c igrf12syn.f
和gcc-lgfortran-o b.out testigrf.o igrf12syn.o
/b。out@AD0AE好。但是,这两个命令gcc-lgfortran-c testigrf.c igrf12syn.f
和gcc-lgfortran-o b.out testigrf.o igrf12syn.o
都没有很好的意义。(我假设,/b.out
有一个新行)。第一个忽略链接选项-lgfortran
,因为-c
表示“仅编译,不链接”。第二个忽略-lgfortran
,因为它位于链接序列中的对象文件之前。对我来说,结果是libgfortran
和libm
中引用的符号出现未定义的引用链接错误,这是应该的。如果您使用非常旧的GCC(我认为是4.7之前的版本),那么您的链接将成功。
end
$ gcc -c -o testigrf.o testigrf.c
$ gfortran -fno-underscoring -c -o igrf12syn.o igrf12syn.f
$ gfortran -o testigrf testigrf.o igrf12syn.o