Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确链接gfortran和gcc?_C_Gcc_Compiler Errors_Fortran_Gfortran - Fatal编程技术网

如何正确链接gfortran和gcc?

如何正确链接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

我试图编写一个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, 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