在现代 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 并坚持第一条路,摆脱类型绑定过程。