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.