Thanks to visit codestin.com
Credit goes to github.com

Skip to content

BUG: f2py does not properly wrap functions #23598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
HugoMVale opened this issue Apr 16, 2023 · 4 comments · Fixed by #23600
Closed

BUG: f2py does not properly wrap functions #23598

HugoMVale opened this issue Apr 16, 2023 · 4 comments · Fixed by #23600

Comments

@HugoMVale
Copy link

HugoMVale commented Apr 16, 2023

Describe the issue:

I confess I can't determine if this issue is a bug or an implicit lack of feature (partial inability to deal with functions), which does not raise an error, yet produces strange results.

f2py works as as expected for subroutines. In contrast, with functions there are 2 issues:

  • When functions are defined using the syntax result-type function function-name(arguments, ) result (result-name), the result-type is always interpreted as real. There is a type mismatch warning. The function "works", but "just" returns the wrong type.

  • When functions are defined using the classical syntax function function-name(arguments, ), the result-type is correctly interpreted, but f2py raises a warning about the number of arguments. Despite the warning, the function seems to work well.

An example can be found here.

Reproduce the code example:

# original fortran functions

integer function intproduct(a, b) result(res)
  !! Product of two integers
  !! This will not work as as expected
  integer, intent(in) :: a, b
  res = a*b
end function

function intproduct2(a, b)
  !! Product of two integers
  !! This will not work as as expected
  integer, intent(in) :: a, b
  integer :: intproduct2
  intproduct2 = a*b
end function

Error message:

# This is not the error message (there is no error), but the intermediate pyf file

function intproduct(a,b) result (res) ! in :fortranmodule:mathtools.f90:mathtools
  integer intent(in) :: a
  integer intent(in) :: b
  real :: res                        ! wrong
end function intproduct
function intproduct2(a,b) ! in :fortranmodule:mathtools.f90:mathtools
  integer intent(in) :: a
  integer intent(in) :: b
  integer :: intproduct2             ! ok
end function intproduct2

Runtime information:

C:\Users\X\AppData\Local\Temp\tmpdov3t9ts\src.win-amd64-3.11\fortranmodule-f2pywrappers2.f90:5:46:

    5 |       subroutine f2pywrap_mathtools_intproduct (intproductf2pywrap, a, b&
      |                                              1
......
   44 |       subroutine f2pywrap_mathtools_intproduct (intproductf2pywrap, intp&
      |                                              2
Warning: Type mismatch in argument 'intproduct' (REAL(4)/INTEGER(4)) between (1) and (2)
C:\Users\X\AppData\Local\Temp\tmpdov3t9ts\src.win-amd64-3.11\fortranmodule-f2pywrappers2.f90:13:47:

   13 |       subroutine f2pywrap_mathtools_intproduct2 (intproduct2f2pywrap, a,&
      |                                               1
......
   51 |       subroutine f2pywrap_mathtools_intproduct2 (intproduct2f2pywrap, in&
      |                                               2
Warning: 'f2pywrap_mathtools_intproduct2' has the wrong number of arguments between (1) and (2)

Context for the issue:

No response

@HaoZeke
Copy link
Member

HaoZeke commented Apr 16, 2023

Thanks for this, could you also add the commands used to run f2py and the output of f2py -v? As of 1.25.0.dev0+1180.gac22f74b9 running:

f2py -c test_bug.f90 -m blah
python -c "import blah; print(blah.intproduct(1, 2))" # returns junk
# 0.0007104013347998261
python -c "import blah; print(blah.intproduct(1, 2))" # works
# 2

The wrappers (from f2py test_bug.f90 -m blah) are wrong:

C     -*- fortran -*-
C     This file is autogenerated with f2py (version:1.25.0.dev0+1180.gac22f74b9)
C     It contains Fortran 77 wrappers to fortran functions.

      subroutine f2pywrapintproduct (intproductf2pywrap, a, b)
      external intproduct
      integer a
      integer b
      real intproductf2pywrap
      real  intproduct !! Nope
      intproductf2pywrap = intproduct(a, b)
      end


      subroutine f2pywrapintproduct2 (intproduct2f2pywrap, a, b)
      external intproduct2
      integer a
      integer b
      integer intproduct2f2pywrap
      integer  intproduct2
      intproduct2f2pywrap = intproduct2(a, b)
      end

And as noted in the issue, this is also seen in the pyf from f2py -h blah.pyf test_bug.f90:

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

function intproduct(a,b) result (res) ! in test_bug.f90
    integer intent(in) :: a
    integer intent(in) :: b
    real :: res
end function intproduct
function intproduct2(a,b) ! in test_bug.f90
    integer intent(in) :: a
    integer intent(in) :: b
    integer :: intproduct2
end function intproduct2

! This file was auto-generated with f2py (version:1.25.0.dev0+1180.gac22f74b9).
! See:
! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e

tl;DR

  • I can't reproduce the warning, but I can reproduce the incorrectly inferred type for intproduct
  • The bug regarding wrong wrappers and return types is present even in NumPy 1.18.1

@HugoMVale
Copy link
Author

My fortran source file is a module. No warnings are raised if the file only contains the functions.

! test_bug_mod.f90

module test_bug
    !! A simple module to debug f2py.
    implicit none
    private
    public :: intproduct, intproduct2
 
contains

    integer function intproduct(a, b) result(res)
    !! Product of two integers
    !! This will not work as expected
    integer, intent(in) :: a, b
    res = a*b
    end function

    function intproduct2(a, b)
    !! Product of two integers
    !! This will not work as expected
    integer, intent(in) :: a, b
    integer :: intproduct2
    intproduct2 = a*b
    end function

end module

I build it with a 3 step procedure:

:: Create function signatures
f2py test_bug_mod.f90 -m fortranmodule -h test_bug_mod.pyf
:: Generate module 
gfortran -c -O3 test_bug_mod.f90
:: Build extension module
f2py -c test_bug_mod.pyf test_bug_mod.f90 --fcompiler=gnu95

Here is the output.txt

Running the following code snippet:

from fortranmodule import test_bug as test

a = 2
b = 3

result = test.intproduct(a, b)
print('result type: ', type(result))
print('result: ', result)

result = test.intproduct2(a, b)
print('result type: ', type(result))
print('result: ', result)

produces the following output:

result type:  <class 'float'>
result:  6.0
result type:  <class 'int'>
result:  6

@HaoZeke
Copy link
Member

HaoZeke commented Apr 17, 2023

Thanks for the clarifications! The error in return types is fixed by #23600, both with and without modules. The warning should also be silenced.

@HugoMVale
Copy link
Author

Thanks for addressing the issue so quickly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants