Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
541 views
in Technique[技术] by (71.8m points)

linker - How to call a function in Fortran that is defined in a separate file?

I am trying to compile some really old code (1986 and before). This code references an external function. Today's compilers ask for far more code to make this work. And I keep failing. I now created a small hello world program, which demonstrates the problem.

hello.for

  PROGRAM hello
    USE func        
    PRINT *, "Hello World!"
    PRINT *, f ()    
  END PROGRAM hello

func.for

  MODULE func
    PUBLIC f
  CONTAINS
    FUNCTION f () 
        f='Hello Func'
    END FUNCTION
  END MODULE

This has not only one, but two problems:

  • How do I define the return type? Docs tell <type> FUNCTION <function> or FUNCTION <function> () <type>::<something> , but neither works.
  • How do I make the linker find the function?

gfortran -c func.for works (if I use the default return type real) and creates a mod file but linking does not work

$ gfortran  hello.for 
/tmp/ccHNzcXA.o: In function `MAIN__':
hello.for:(.text+0xa4): undefined reference to `__func_MOD_f'
collect2: error: ld returned 1 exit status

__func_MOD_f is not contained in the mod file, but in the o file there is func.for__func_MOD_f.

Any idea?

thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have two issues, the delcaration of f and properly linking the module.

First, compiling the module yields the error:

% gfortran -c func.f
func.f:5:8:

       f='Hello Func'
        1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)

This error is due to implicit typing of f and an incompatible assignment. Fixing this is simple, declare f explicitly as a character instead of an implicit type. Add:

character(len=30) :: f

to the function and now your module compiles. Here is the modified module:

  MODULE func
  PUBLIC f
  CONTAINS
  FUNCTION f ()
  character(len=30) :: f
  f='Hello Func'
  END FUNCTION
  END MODULE

Your second problem is linking. Your command:

gfortran  hello.for  

fails because you did not specify the module object. If you already compiled the module you would specify:

gfortran hello.for func.o

if you were compiling them both at the same time you would do:

gfortran -o hworld func.for hello.for

if you are compiling everything individually:

gfortran -c func.for
gfortran -c hello.for
gfortran -o hworld hello.o func.o

Any of these will compile and run:

% ./hworld 
 Hello World!
 Hello Func   

If you are modernizing your code, it would also be worth adding implicit none to avoid any implicit typing and declaring explicit variables for everything. e.g.:

module func
  implicit none
contains
function f 
  implicit none
  character(len=30) :: f
  f='Hello Func'
end function f
end module func

and

program hello
  use func
  implicit none        
  print *, "Hello World!"
  print *, f ()    
end program hello

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...