gpt4 book ai didi

c - 如何正确链接gfortran和gcc?

转载 作者:行者123 更新时间:2023-11-30 17:05:32 25 4
gpt4 key购买 nike

我正在尝试编写一个调用一段 Fortran 代码的 C 函数。我认为尝试直接链接 Fortran 代码比尝试将 Fortran 重写为 C 会更容易。我在 Mac 上使用 gcc/g++/gfortran,直接下载了二进制文件并安装了它们。

Fortran 代码位于 https://www.ngdc.noaa.gov/IAGA/vmod/igrf12.f 。我要调用的具体子例程是subroutine 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;
}

我用来编译和调用它的命令是:

/usr/local/bin/gcc -lgfortran -c testigrf.c igrf12.f
/usr/local/bin/gcc -lgfortran -o b.out testigrf.o igrf12.o

我得到的错误是:

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 文件,其中显示两个 main 函数。但是,我不确定如何更改 Fortran 代码来消除此错误。

所以我的问题如下:1. 如何更改 Fortran 或 C 代码来解决此问题?特别是,由于 Fortran 代码以 PROGRAM IGRF

开头
  • 我是否正确调用了 igrf12syn 例程?我担心我没有正确调用它。我也可能在传递变量方面做得很糟糕,这必须通过引用来完成。
  • 感谢您的帮助,如果我在调用例程时做了一些非常愚蠢的事情,请告诉我。

    最佳答案

    首先,您的 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_,编译器对此一无所知。

    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;

    double r, th, ph,year,alt2,lat,colat,elong,x,y,z,f,itype;

    并改变:

    igrf12syn(&isv,&year,&isv,&r, &th, &ph,x,y,z,f);

    至:

    igrf12syn(&isv,&year,&itype,&r, &th, &ph,&x,&y,&z,&f);

    这将使编译器满意,尽管它可能无法表达您的意图,我不清楚。

    您了解不能将两个程序链接到一个程序中,因为链接器会发现重复的 main 函数。你需要链接仅包含 Fortran 子例程 igrf12syn 的 C 主程序。

    接下来,下载并保存文件https://www.ngdc.noaa.gov/IAGA/vmod/igrf12.f。在文本/编程编辑器中打开它。选择所有行 - 完整行,包括前导空格 - 组成子例程 igrf12syn,来自:

      subroutine igrf12syn (isv,date,itype,alt,colat,elong,x,y,z,f)

    至:

     end

    将此选择完全按照复制到新文件 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 - 如何正确链接gfortran和gcc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35245733/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com