1

C ルーチンを呼び出してメジャーを計算する FORTRAN コードがあります。FORTRAN コードは次のとおりです。

program fortran
implicit none
interface
double precision function fpli_hv(A, d, n)
real :: A(5,3)
integer :: d, n
end function fpli_hv
end interface
real :: A(5,3)
double precision :: HV
integer :: i, j
A(1,:) = (/1.1,3.2,2.0/)
A(2,:) = (/6.3,5.2,7.2/)
A(3,:) = (/3.3,4.4,9.1/)
A(4,:) = (/3.3,5.2,2.1/)
A(5,:) = (/7.6,1.7,4.3/)
HV = fpli_hv(A, 3, 5)
end program fortran  

c 関数は次のようになります。

double fpli_hv(double *front, int d, int n, double *ref);  

c と fortran をクラブ化するには、makefile に Makefil.lib を含める必要があります。私はそうし、次のようにメイクファイルを準備しました。

# The makefile should contain a set of suffix rules. All suffixes must
# be defined. In this case we will have .o for object files, .c for
# C files, and .f for Fortran files.
.SUFFIXES: .o .c .f90

# LIBRARY:
LIBHV = /gpfs0/home/shafiiha/programs/hv-2.0rc1-src/fpli_hv.a
#include Makefile.lib

# Define the C and Fortran compilers to be used in this makefile:
CC=
FC=gfortran -ffree-form -c

# Define flags to be used by the C and Fortran compilers:
CFLAGS =    
FFLAGS =

# Define include to be used by the C and Fortran compilers:
C_INCLUDES =     
F_INCLUDES = fortran.f90

# The linker executable in this case must be the MPI Fortran compiler
# to build a mixed C and Fortran MPI code:
LINK = gfortran

# Define values of parameters that appear in the source codes:
DEFINES =

# Define the list of object files for the linker. The linker will use
# those files to build the executable.
OBJECTS = fortran.o

# The rule that makes the drv executable (note that libraries have
# been specified by the mpif90 linker):
fortran: $(OBJECTS) 
    $(LINK) -o fortran $(OBJECTS) $(LIBHV)

# The rule that makes all object files from C sources:
.c.o:
    $(CC) $(CFLAGS) $(C_INCLUDES) $(DEFINES) $<

# The rule that makes all object files from Fortran sources:
.f90.o:
    $(FC)  $(FFLAGS)  $(F_INCLUDES) $^ $(LIBHV)

# The rule for deleting object files no longer needed after using
# make for drv:
clean:
    rm  *.o

しかし、それを作成すると、次のメッセージが表示されます。

gfortran -o fortran fortran.o /gpfs0/home/shafiiha/programs/hv-2.0rc1-src/fpli_hv.a  
fortran.o: In function `MAIN__':  
fortran.f90:(.text+0x548): undefined reference to `fpli_hv_'  
collect2: ld returned 1 exit status  
make: *** [fortran] Error 1  

このエラーが発生する理由を教えてください。どうもありがとう。

4

3 に答える 3

5

この時代に Fortran から C を呼び出す最良の方法は、ISO C バインディングを使用することです。あなたの問題は、C または標準ライブラリのルーチンとの衝突を避けるために Fortran がデフォルトで行う名前マングリングであり、通常はアンダースコアを追加します。ISO C バインディングを使用すると、呼び出されたルーチンの正確な名前を指定して、名前マングリングをオーバーライドし、引数で Fortran-C の一貫性を簡単に実現できます。Fortran 側では、C ルーチンを記述するインターフェースを作成します。ここには以前の回答があり、gfortran マニュアルに例があります。ISO C Binding は Fortran 2003 言語標準の一部であるため、例は gfortran に固有のものではありません。

于 2012-05-31T15:52:00.360 に答える
4

すでにインターフェースを作成している場合 (これは素晴らしいことです!)、ほとんどの Fortran コンパイラの最新バージョンがすでに持っている iso_c_binding モジュールを使用して、アンダースコアや大文字と小文字の区別を気にする必要がなくなります。

interface
  function fpli_hv(A, d, n) bind(C)
   use iso_c_binding
   implicit none

   real(kind=c_double) :: fpli_hv
   integer(kind=c_int), value :: d, n
   real(kind=c_float) :: A(5,3)

  end function fpli_hv
end interface
于 2012-05-31T15:53:29.973 に答える
0

包む

double fpli_hv(double *front, int d, int n, double *ref); 

void FPLI_HV_(double *front, int* d, int* n, double *ref, double* returnvalue); 

Fortran オブジェクトは _ で終わるものだけを理解し、すべての関数パスはポインターによって行われます。

(以下のコメントを編集)。

于 2012-05-31T15:25:33.510 に答える