2

gfortran-gcc 互換になるように、このコード(バックアップとしての要点)を変更しようとしています。

  • [VALUE]タグは外しました
  • タグの代わりに gfortran のフラグPOINTERで使用-fcray-pointer[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。オペレーティング システムとコンパイラの仕様は、この質問と同じです。

4

2 に答える 2

4

Fortran は、Fortran から C へのチュートリアルの最初の文で説明されているように、参照によって変数を渡します。だからあなた:

  1. を単に削除することはできません[VALUE]。最新の VALUE 属性を追加するか、ポインターを渡すように C コードを変更する必要があります。

  2. の Fortran 側でポインタを使用するべきではなく[REFERENCE]、削除するだけです。

  3. 最近では通常、コンパイラに実際の名前マングリングを使用するsubroutine_name_か (アンダースコアが追加され、名前は小文字)、modernbind(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属性を使用すると、他の回答に表示されるC一時変数をすべて導入する必要はありません。が正しく機能するために必要bind(C)です。VALUEFortran プロシージャを呼び出すコードを書き直す必要がなくなります。

最新の最適なエクスペリエンスを得るbind(C,name="any_name_you_want")には、正確なリンケージ シンボル名を設定します。

于 2018-12-02T23:43:15.480 に答える