4

I've run into what I think might be a bug in f2py and callbacks to python. Or, maybe I'm not using things correctly. I have created a very minimal example which illustrates my problem at:

https://github.com/soylentdeen/fluffy-kumquat

To reproduce my problems:

python 2.7.8

gfortran

callback.f:

    subroutine test 
    cf2py intent(callback, hide) fred
    cf2py intent(callback, hide) bambam
    external fred
    external bambam
    integer n
    n = 4
    write (*,*) "Yabba Dabba Doo! In Subroutine TEST" 
    write (*,*) "Calling Fred:"
    call fred
    write (*,*) "Calling Bambam:"
    call bambam(n)
    end

nocallback.f:

      subroutine barney
      write (*,*) "In Subroutine BARNEY"
      write (*,*) "Calling Subroutine TEST"
      call test
      end

flintstone.pyf

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

python module test__user__routines 
    interface test_user_interface 
        subroutine fred ! in :flintstone:callback.f:test:unknown_interface
            intent(callback,hide) fred
        end subroutine fred
        subroutine bambam(n) ! in :flintstone:callback.f:test:unknown_interface
            intent(callback,hide) bambam
            integer :: n
        end subroutine bambam
    end interface test_user_interface
end python module test__user__routines
python module flintstone ! in 
    interface  ! in :flintstone
        subroutine test ! in :flintstone:callback.f
            use test__user__routines, fred=>fred, bambam=>bambam
            intent(callback, hide) fred
            external fred
            intent(callback,hide) bambam
            external bambam
        end subroutine test
        subroutine barney ! in :flintstone:nocallback.f
        external test
        end subroutine barney
        end interface 
end python module flintstone

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

cb.py

import flintstone

def fred():
    print "fred!"

def bambam(number):
    print("bambam: I want %d Brontosaurus Burgers!" % number)

flintstone.fred = fred
flintstone.bambam = bambam

flintstone.test()
flintstone.barney()

f2py -c -m flintstone flintstone.pyf callback.f nocallback.f

ipython> run cb.py

I get the following output:

In [1]: run cb.py
 Yabba Dabba Doo! In Subroutine TEST
 Calling Fred:
fred!
 Calling Bambam:
bambam: I want 4 Brontosaurus Burgers!
 In Subroutine BARNEY
 Calling Subroutine TEST
 Yabba Dabba Doo! In Subroutine TEST
 Calling Fred:
fred!
 Calling Bambam:
capi_return is NULL
Call-back cb_bambam_in_test__user__routines failed.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/deen/Code/Python/sandbox/fluffy-kumquat/cb.py in <module>()
     12
     13 flintstone.test()
---> 14 flintstone.barney()
     15 
     16 

TypeError: bambam() takes exactly 1 argument (0 given)

The output suggests that the bambam(n) callback in the test subroutine in callback.f works when it is called directly from the python routine, but not when it is called indirectly from the barney subroutine in nocallback.f

For more information, please have a look at the github repository. I've reproduced the behavior on both linux and mac. I'm not sure if this is an error in the way I'm using the code, or if it is an actual bug. Any and all help would be very much appreciated.

Cheers,

C

EDIT

The error was in the .pyf file. Quoting a kindly soul from the numpy-discussion listserv:

What you observe, is not a f2py bug. When f2py sees a code like

 subroutine foo
  call bar
 end subroutine foo

then it will not make an attempt to analyze bar because of implicit assumption that all statements that has no references to foo arguments are irrelevant for wrapper function generation. For your example, f2py needs some help. Try the following signature in .pyf file:

 subroutine barney ! in :flintstone:nocallback.f
     use test__user__routines, fred=>fred, bambam=>bambam
     intent(callback, hide) fred
     external fred
     intent(callback,hide) bambam
     external bambam
 end subroutine barney

Btw, instead of

f2py -c -m flintstone flintstone.pyf callback.f nocallback.f

use

f2py -c flintstone.pyf callback.f nocallback.f

because module name comes from the .pyf file.

soylentdeen
  • 101
  • 7

0 Answers0