如何调用在单独文件中定义的 Fortran 函数?
How to call a function in Fortran that is defined in a separate file?
我正在尝试编译一些非常古老的代码(1986 年及之前)。此代码引用外部函数。今天的编译器需要更多的代码来完成这项工作。我一直在失败。
我现在创建了一个小的 hello world 程序,它演示了这个问题。
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
这不仅有一个问题,还有两个问题:
- 如何定义 return 类型?文档告诉
<type> FUNCTION <function>
或 FUNCTION <function> () <type>::<something>
,但都不起作用。
- 如何让链接器找到函数?
gfortran -c func.for
有效(如果我使用默认的 return 类型真实)并创建一个 mod 文件但链接不起作用
$ 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
不 包含在 mod 文件中,但在 o 文件中有 func.for__func_MOD_f
.
有什么想法吗?
谢谢
您有两个问题,f
的声明和正确链接模块。
首先,编译模块产生错误:
% gfortran -c func.f
func.f:5:8:
f='Hello Func'
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
此错误是由于 f
的隐式键入和不兼容的赋值造成的。解决这个问题很简单,将 f
显式声明为 character
而不是隐式类型。添加:
character(len=30) :: f
添加到函数中,现在您的模块可以编译了。这是修改后的模块:
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
character(len=30) :: f
f='Hello Func'
END FUNCTION
END MODULE
你的第二个问题是链接。您的命令:
gfortran hello.for
失败,因为您没有指定模块对象。如果您已经编译了模块,您将指定:
gfortran hello.for func.o
如果你同时编译它们,你会这样做:
gfortran -o hworld func.for hello.for
如果您单独编译所有内容:
gfortran -c func.for
gfortran -c hello.for
gfortran -o hworld hello.o func.o
其中任何一个都可以编译并且 运行:
% ./hworld
Hello World!
Hello Func
如果您要对代码进行现代化改造,还值得添加 implicit none
以避免任何隐式键入并为所有内容声明显式变量。例如:
module func
implicit none
contains
function f
implicit none
character(len=30) :: f
f='Hello Func'
end function f
end module func
和
program hello
use func
implicit none
print *, "Hello World!"
print *, f ()
end program hello
我正在尝试编译一些非常古老的代码(1986 年及之前)。此代码引用外部函数。今天的编译器需要更多的代码来完成这项工作。我一直在失败。 我现在创建了一个小的 hello world 程序,它演示了这个问题。
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
这不仅有一个问题,还有两个问题:
- 如何定义 return 类型?文档告诉
<type> FUNCTION <function>
或FUNCTION <function> () <type>::<something>
,但都不起作用。 - 如何让链接器找到函数?
gfortran -c func.for
有效(如果我使用默认的 return 类型真实)并创建一个 mod 文件但链接不起作用
$ 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
不 包含在 mod 文件中,但在 o 文件中有 func.for__func_MOD_f
.
有什么想法吗?
谢谢
您有两个问题,f
的声明和正确链接模块。
首先,编译模块产生错误:
% gfortran -c func.f
func.f:5:8:
f='Hello Func'
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
此错误是由于 f
的隐式键入和不兼容的赋值造成的。解决这个问题很简单,将 f
显式声明为 character
而不是隐式类型。添加:
character(len=30) :: f
添加到函数中,现在您的模块可以编译了。这是修改后的模块:
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
character(len=30) :: f
f='Hello Func'
END FUNCTION
END MODULE
你的第二个问题是链接。您的命令:
gfortran hello.for
失败,因为您没有指定模块对象。如果您已经编译了模块,您将指定:
gfortran hello.for func.o
如果你同时编译它们,你会这样做:
gfortran -o hworld func.for hello.for
如果您单独编译所有内容:
gfortran -c func.for
gfortran -c hello.for
gfortran -o hworld hello.o func.o
其中任何一个都可以编译并且 运行:
% ./hworld
Hello World!
Hello Func
如果您要对代码进行现代化改造,还值得添加 implicit none
以避免任何隐式键入并为所有内容声明显式变量。例如:
module func
implicit none
contains
function f
implicit none
character(len=30) :: f
f='Hello Func'
end function f
end module func
和
program hello
use func
implicit none
print *, "Hello World!"
print *, f ()
end program hello