繁体   English   中英

最小修改使视觉工作室FORTRAN-C混合代码gfortran-gcc兼容

[英]minimum modification to make a visual studio FORTRAN-C mixed code gfortran-gcc compatible

我正在尝试修改此代码gist as back up )以成为gfortran-gcc兼容。

  • 我删除了[VALUE]标签
  • 使用带有-fcray-pointer标志的POINTER用于gfortran,而不是[REFERENCE]标签
  • 删除__stdcall ,因为尝试了#define __stdcall __attribute__((stdcall))导致warning: 'stdcall' attribute ignored [-Wattributes]现在这就是我所拥有的:

C代码CMAIN.C

#include <stdio.h>

extern int FACT_(int n);
extern void PYTHAGORAS_(float a, float b, float *c);

main()
{
    float c;
    printf("Factorial of 7 is: %d\n", FACT_(7));
    PYTHAGORAS_(30, 40, &c);
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);
}

FORTRAN代码FORSUBS.FOR

  INTEGER*4 FUNCTION Fact (n)
  INTEGER*4 n 
  INTEGER*4 i, amt
  amt = 1
  DO i = 1, n
    amt = amt * i
  END DO
  Fact = amt
  END

  SUBROUTINE Pythagoras (a, b, cp)
  REAL*4 a
  REAL*4 b
  POINTER (cp, c)
  REAL*4 c
  c = SQRT (a * a + b * b)
  END

Makefile

all:
    gfortran -c FORSUBS.FOR -fcray-pointer
    gcc -c CMAIN.C
    gfortran -o result.out FORSUBS.o CMAIN.o  
    rm -rf *.o

clean :
    rm -rf *.out *~ *.bak *.o

但是我仍然得到错误:

CMAIN.o:在函数`main'中:

CMAIN.C :(。text + 0x1d):对'FACT_(int)'的未定义引用

CMAIN.C :(。text + 0x4c):未定义引用`PYTHAGORAS_(float,float,float *)'

如果你能帮助我,我将不胜感激:

  • 问题是什么,如何解决?
  • 什么是修改原始代码以使gcc-gfortran与最小变化兼容的最佳方法。

PS1。 也在Reddit分享 PS2。 操作系统和编译器规范与此问题相同。

Fortran通过引用传递变量,如任何Fortran到C教程的第一句中所述。 那么你:

  1. 不能只删除[VALUE] ,你应该添加现代VALUE属性或更改C代码来传递指针。

  2. 不应该在[REFERENCE]的Fortran端使用指针,而只是删除它。

  3. 使用编译器的实际名称mangling,这些天通常是subroutine_name_ (附加的下划线,name是小写)或使用现代bind(C, name="binding_name")属性。

没有现代Fortran,但有VALUE (它只是没有PITA):

  INTEGER*4 FUNCTION Fact (n)
  INTEGER*4, VALUE :: n 
  INTEGER*4 i, amt
  amt = 1
  DO i = 1, n
    amt = amt * i
  END DO
  Fact = amt
  END

  SUBROUTINE Pythagoras (a, b, c) bind(C)
  REAL*4, VALUE :: a
  REAL*4, VALUE :: b
  REAL*4 c
  c = SQRT (a * a + b * b)
  END

而不仅仅是将你的C名改为小写( pythagoras_fact_ )......使用VALUE属性,你不需要介绍你在另一个答案中看到的所有那些临时代码。 VALUE需要bind(C)才能正常工作。 它将避免您重写调用Fortran过程的代码。

为了获得最佳的现代体验,请使用bind(C,name="any_name_you_want")来设置确切的链接符号名称。

除了我的热门评论之外,Fortran还通过引用传递,因此您必须修改.c.for文件。

以下代码有效。 可能有一种更简单的方式来声明事物,但这应该[至少]让你更进一步。 警告 :自Fortran IV以来,我没有做太多的事情,所以我有点生疏了。 我会推迟弗拉基米尔的VALUE解决方案作为一种更好的方式。


#include <stdio.h>

#if 0
extern int fact_(int n);
extern void pythagoras_(float a, float b, float *c);
#else
extern int fact_(int *n);
extern void pythagoras_(float *a, float *b, float *c);
#endif

int
main(void)
{
    float c;
#if 0
    printf("Factorial of 7 is: %d\n", fact_(7));
#else
    int n = 7;
    printf("Factorial of 7 is: %d\n", fact_(&n));
#endif

#if 0
    pythagoras_(30, 40, &c);
#else
    float a = 30;
    float b = 40;
    pythagoras_(&a, &b, &c);
#endif
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);

    return 0;
}

    INTEGER*4 FUNCTION Fact (n)
    INTEGER*4 n
    INTEGER*4 i, amt
    amt = 1
    DO i = 1, n
        amt = amt * i
    END DO
    Fact = amt
    END

    SUBROUTINE Pythagoras (a, b, c)
    REAL*4 a
    REAL*4 b
    REAL*4 c
    c = SQRT (a * a + b * b)
    END

这是程序输出:

Factorial of 7 is: 5040
Hypotenuse if sides 30, 40 is: 50.000000

更新:

我从你的代码中得到了相同的undefined reference错误!

啊哈!

我没有提到的一件事[因为我认为它不会产生影响]是我改变了源文件名以使用全部小写字母(例如CMAIN.C --> cmain.cFORSUBS.FOR --> forsubs.for

这样, nm *.o的输出产生:

 cmain.o:
                 U fact_
0000000000000000 T main
                 U printf
                 U pythagoras_

forsubs.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_

fortran源文件名的更改并不重要。 但是,C源文件名呢!

更重要的是它是文件名后缀 (即.C更改为.c )。

这是因为gcc将[尝试智能]并查看后缀以确定文件所写的语言并进行相应编译。 例如, gcc -c foo.cpp将编译该文件,就好像它是用c++不是 c编写的,就好像命令是: g++ -c foo.cpp

虽然.cpp [更多]通常后缀为一个c++文件名,一个备用后缀c++文件是: .C

也就是说,大多数项目使用.cpp约定,但有些使用.C约定。 偏爱.cpp不是.C的原因之一是Windows文件系统不区分大小写。 所以, .C.c看起来是一样的。 但是,POSIX系统(例如linux,macOSX,iOS,android等)具有区分大小写的文件名,因此可以使用任何约定。

所以, gcc -c CMAIN.C将编译为c++ 这样做c++风格的“名称错误”符号 - 不是我们想要的。 c++ ,完成修改以允许“重载”函数名称。 也就是说,两个[或更多]不同的函数可以具有相同的名称,只要它们使用不同的参数即可。 例如:

void calc(int val);
void calc(int val1,int val2);
void calc(double fval);

如果我们使用CMAIN.C这是nm *.o的输出:

 CMAIN.o:
0000000000000000 T main
                 U printf
                 U _Z11pythagoras_PfS_S_
                 U _Z5fact_Pi

FORSUBS.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_

通过c++filt运行文件以“demangle”我们得到的c++名称:

 CMAIN.o:
0000000000000000 T main
                 U printf
                 U pythagoras_(float*, float*, float*)
                 U fact_(int*)

FORSUBS.o:
0000000000000000 T fact_
0000000000000045 T pythagoras_

因此,尽可能使用小写文件名[建议的最佳做法]。 但是,至少,不要使用.C

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM