Search code examples
fortranf2py

Compiling a module with f2py with an interface


I am trying to compile a fortran module with f2py. It is the following code

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   

that I compile with the following command

f2py.py -c -m my_log_mod_comp my_log_mod.f90

and it results in the following error

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'

I don't really know much about fortran and f2py, so I don't have any idea what is happening. If i use the module in pure fortran it works nicely


Solution

  • F2py appears to be creating another wrapper code which uses the subroutines in your module.

    But it calls directly the subroutines my_log_vector and my_log_array. It seems f2py does not support private. I would delete the private.

    Also be prepared that you won't be able to use the generic my_log in Python. This concept of generics is alien to Python. You may need to delete the generic interface if deleting private does not make it compilable. You should definitely delete the public :: my_log.

    Unfortunately, f2py does not support all features of modern Fortran.

    The code I tested:

    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   
    

    compilation:

    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