【问题标题】:Compiling a module with f2py with an interface使用 f2py 编译带有接口的模块
【发布时间】:2017-06-23 18:37:13
【问题描述】:

我正在尝试用 f2py 编译一个 fortran 模块。就是下面的代码

module my_log_mod

   implicit none

    interface my_log
        module procedure my_log_array
        module procedure my_log_vector
    end interface my_log

   private  ! hides items not listed on public statement 
   public :: my_log


contains

    subroutine my_log_array(a,res)
        double precision, dimension (:,:), intent (in) :: a
        double precision, dimension (:,:), intent (out) :: res

        where (a>1.0)
            res = log(a)
        else where
            res = 0.D0
        end where
    end subroutine  

    subroutine my_log_vector(a,res)
        double precision, dimension (:), intent (in) :: a
        double precision, dimension (:), intent (out) :: res

        where (a>1.0)
            res = log(a)
        else where
            res = 0.D0
        end where
    end subroutine  

end module my_log_mod   

我使用以下命令编译

f2py.py -c -m my_log_mod_comp my_log_mod.f90

它会导致以下错误

C:\Users\weisshau\AppData\Local\Temp\tmpf0apqa7s\src.win32-3.6\my_log_mod_comp-f2pywrappers2.f90:7:28:

       use my_log_mod, only : my_log_array
                            1
Error: Symbol 'my_log_array' referenced at (1) not found in module 'my_log_mod'
C:\Users\weisshau\AppData\Local\Temp\tmpf0apqa7s\src.win32-3.6\my_log_mod_comp-f2pywrappers2.f90:18:28:

       use my_log_mod, only : my_log_vector
                            1
Error: Symbol 'my_log_vector' referenced at (1) not found in module 'my_log_mod'

我不太了解 fortran 和 f2py,所以我不知道发生了什么。如果我在纯 fortran 中使用该模块,它会很好地工作

【问题讨论】:

    标签: fortran f2py


    【解决方案1】:

    F2py 似乎正在创建另一个使用模块中的子例程的包装器代码。

    但它直接调用子程序my_log_vectormy_log_array。 f2py 似乎不支持private。我会删除private

    还要做好准备,您将无法在 Python 中使用通用 my_log。泛型的这个概念与 Python 格格不入。如果删除 private 不能使其可编译,您可能需要删除通用接口。你绝对应该删除public :: my_log

    很遗憾,f2py 不支持现代 Fortran 的所有功能。

    我测试的代码:

    module my_log_mod
    
       implicit none
    
        interface my_log
            module procedure my_log_array
            module procedure my_log_vector
        end interface my_log
    
    contains
    
        subroutine my_log_array(a,res)
            double precision, dimension (:,:), intent (in) :: a
            double precision, dimension (:,:), intent (out) :: res
    
            where (a>1.0)
                res = log(a)
            else where
                res = 0.D0
            end where
        end subroutine  
    
        subroutine my_log_vector(a,res)
            double precision, dimension (:), intent (in) :: a
            double precision, dimension (:), intent (out) :: res
    
            where (a>1.0)
                res = log(a)
            else where
                res = 0.D0
            end where
        end subroutine  
    
    end module my_log_mod   
    

    编译:

    f2py -c -m my_log_mod_comp my_log_mod.f90
    
    ...
    
    Post-processing...
            Block: my_log_mod_comp
                            Block: my_log_mod
                                    Block: my_log
                                    Block: my_log_array
                                    Block: my_log_vector
    Post-processing (stage 2)...
            Block: my_log_mod_comp
                    Block: unknown_interface
                            Block: my_log_mod
                                    Block: my_log_array
                                    Block: my_log_vector
    Building modules...
            Building module "my_log_mod_comp"...
                    Constructing F90 module support for "my_log_mod"...
                    Creating wrapper for Fortran subroutine "my_log_array"
                          res = my_log_array(a)
                              res = my_log_array(a)
                    Creating wrapper for Fortran subroutine "my_log_vector"("my_log_vector")...
                            Constructing wrapper function "my_log_mod.my_log_vector"...
                              res = my_log_vector(a)
            Wrote C/API module "my_log_mod_comp" to file "/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_compmodule.c"
            Fortran 90 wrappers are saved to "/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.f90"
    
    ...
    
    gfortran:f90: /tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.f90
    /usr/bin/gfortran -Wall -g -Wall -g -shared /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_compmodule.o /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/fortranobject.o /tmp/tmp7e5v0u/my_log_mod.o /tmp/tmp7e5v0u/tmp/tmp7e5v0u/src.linux-x86_64-2.7/my_log_mod_comp-f2pywrappers2.o -L/usr/lib64 -lpython2.7 -lgfortran -o ./my_log_mod_comp.so
    Removing build directory /tmp/tmp7e5v0u
    

    【讨论】:

    • 非常感谢您的回答。我尝试了您的两个建议,但仍然无效。也许我应该将我的问题扩大到:“我如何编写一个将任意数组作为输入和输出并将其与 f2py 一起使用的 fortran 子程序”
    • 它在我的电脑上运行。至少使用您提供的代码。解释它不起作用。这句话并没有说明什么。什么意思?
    • “我如何编写一个将任意数组作为输入和输出并与 f2py 一起使用的 fortran 子例程” 你不会。这就是我在回答中提出的观点。
    • 我尝试删除接口块之后的两行并一起删除接口块,但它总是失败,并出现与我的问题相同的错误。对你来说第二点:好吧,这很高兴知道,但这不是 f2py 的一个巨大缺点吗?
    • 您可以在 Python 中为这两个创建一个包装器。 Python 使用鸭子类型,而 Fortran 使用带有特定子例程的泛型。这两种方法不兼容。可以想象 f2py 为您创建了这个包装器,但事实并非如此。我重复我的回答:不幸的是,f2py 不支持现代 Fortran 的所有功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多