在现代 Fortran 中的模块中使用子例程加载派生类型
Loading derived types with a subroutine within a module in modern Fortran
目标:使用子例程 load_things
加载类型为 su2
的结构库。
运行 gfortran simple.f90
产生
Undefined symbols for architecture x86_64:
"_load_things_", referenced from:
_MAIN__ in cc7DuxGQ.o
(maybe you meant: ___myclass_MOD_load_things_sub)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
主要程序如下:
program simple
use myClass
implicit none
integer :: nThings
type ( su2 ) :: reflections
call load_things ( nThings, reflections )
end program simple
模块定义为:
module myClass
implicit none
type :: su2
integer :: matrix_obj ( 1 : 2, 1 : 2 )
contains
private
procedure, nopass, public :: load_things => load_things_sub
end type su2
private load_things_sub
contains
subroutine load_things_sub ( nThings, U )
integer, intent ( out ) :: nThings
type ( su2 ), intent ( out ), allocatable :: U ( : )
nThings = 2
allocate ( U ( nThings ) )
U ( 1 ) % matrix_obj = reshape ( [ 0, 1, 1, 0 ], [ 2, 2 ] )
U ( 2 ) % matrix_obj = reshape ( [ 0, 1, 1, 0 ], [ 2, 2 ] )
end subroutine load_things_sub
end module myClass
研究了以下网页但没有成功:Correct use of modules, subroutines and functions in fortran、
Fortran 90 - to transmit values from main subroutine to the functions and other subroutines,
Fortran: Calling a function in a module from a procedure in another module,
Fortran 90 How to call a function in a subroutine in a module?
您的模块没有名为 load_things
的子例程 - 它有一个名为 load_things_sub
的子例程。选择名称的正确变体,然后适当更正其他语句中的名称。
在最初提交此答案后,OP 向模块添加了一条私有语句,使 load_things_sub
在使用该模块的范围内无法访问。在没有其他信息的情况下,private声明应该删除。
通过绑定引用 load_thing_sub
等过程毫无意义。将其作为正常程序引用即可。
请注意,列出的许多参考资料都是针对 Fortran 90 的。绑定是在 Fortran 2003 中引入的。
因为 load_things
是派生类型reflections
的绑定名称。正如答案所说,它不是子例程的名称。
正如 IanH 所说,您可以将代码更改为
call load_things_sub ( nThings, reflections )
但您还需要将其设为模块的 public 实体。您可能想要使用类型绑定方式,以便它可以保持私有(类型本身的绑定是可访问的):
call reflections%load_things(nThings, reflections)
这引出了另一组要点:您不能执行上述操作。
您正在使用 nopass
进行绑定,因为该类型的虚拟参数是一个可分配数组:您不能使用 pass
。但是,在您的主程序中,虚拟参数 reflections
是不可分配的标量:那里不匹配,因此 call load_things_sub(nThings, reflections)
无效。
进一步
type ( su2 ), allocatable :: reflections(:)
call reflections%load_things ( nThings, reflections )
本身无效。首先,对于call reflections%...
,必须分配reflections
。其次,使用 reflections
数组 nopass
不允许用于绑定。
那会让你去哪里?好吧,你必须修复 reflections
的可分配性,但最简单的事情可能是继续制作 load_things_sub
public 并坚持第一条路,摆脱类型绑定过程。
目标:使用子例程 load_things
加载类型为 su2
的结构库。
运行 gfortran simple.f90
产生
Undefined symbols for architecture x86_64:
"_load_things_", referenced from:
_MAIN__ in cc7DuxGQ.o
(maybe you meant: ___myclass_MOD_load_things_sub)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
主要程序如下:
program simple
use myClass
implicit none
integer :: nThings
type ( su2 ) :: reflections
call load_things ( nThings, reflections )
end program simple
模块定义为:
module myClass
implicit none
type :: su2
integer :: matrix_obj ( 1 : 2, 1 : 2 )
contains
private
procedure, nopass, public :: load_things => load_things_sub
end type su2
private load_things_sub
contains
subroutine load_things_sub ( nThings, U )
integer, intent ( out ) :: nThings
type ( su2 ), intent ( out ), allocatable :: U ( : )
nThings = 2
allocate ( U ( nThings ) )
U ( 1 ) % matrix_obj = reshape ( [ 0, 1, 1, 0 ], [ 2, 2 ] )
U ( 2 ) % matrix_obj = reshape ( [ 0, 1, 1, 0 ], [ 2, 2 ] )
end subroutine load_things_sub
end module myClass
研究了以下网页但没有成功:Correct use of modules, subroutines and functions in fortran、
Fortran 90 - to transmit values from main subroutine to the functions and other subroutines,
Fortran: Calling a function in a module from a procedure in another module,
Fortran 90 How to call a function in a subroutine in a module?
您的模块没有名为 load_things
的子例程 - 它有一个名为 load_things_sub
的子例程。选择名称的正确变体,然后适当更正其他语句中的名称。
在最初提交此答案后,OP 向模块添加了一条私有语句,使 load_things_sub
在使用该模块的范围内无法访问。在没有其他信息的情况下,private声明应该删除。
通过绑定引用 load_thing_sub
等过程毫无意义。将其作为正常程序引用即可。
请注意,列出的许多参考资料都是针对 Fortran 90 的。绑定是在 Fortran 2003 中引入的。
因为load_things
是派生类型reflections
的绑定名称。正如答案所说,它不是子例程的名称。
正如 IanH 所说,您可以将代码更改为
call load_things_sub ( nThings, reflections )
但您还需要将其设为模块的 public 实体。您可能想要使用类型绑定方式,以便它可以保持私有(类型本身的绑定是可访问的):
call reflections%load_things(nThings, reflections)
这引出了另一组要点:您不能执行上述操作。
您正在使用 nopass
进行绑定,因为该类型的虚拟参数是一个可分配数组:您不能使用 pass
。但是,在您的主程序中,虚拟参数 reflections
是不可分配的标量:那里不匹配,因此 call load_things_sub(nThings, reflections)
无效。
进一步
type ( su2 ), allocatable :: reflections(:)
call reflections%load_things ( nThings, reflections )
本身无效。首先,对于call reflections%...
,必须分配reflections
。其次,使用 reflections
数组 nopass
不允许用于绑定。
那会让你去哪里?好吧,你必须修复 reflections
的可分配性,但最简单的事情可能是继续制作 load_things_sub
public 并坚持第一条路,摆脱类型绑定过程。