File size: 3,989 Bytes
c011401 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
Title: Wrapping F compiled Fortran 90 modules with F2PY ================================================ Rationale: The F compiler does not support external procedures which makes it impossible to use it in F2PY in a normal way. This document describes a workaround to this problem so that F compiled codes can be still wrapped with F2PY. Author: Pearu Peterson Date: May 8, 2002 Acknowledgement: Thanks to Siegfried Gonzi who hammered me to produce this document. Normally wrapping Fortran 90 modules to Python using F2PY is carried out with the following command f2py -c -m fun foo.f90 where file foo.f90 contains, for example, module foo public :: bar contains subroutine bar (a) integer,intent(inout) :: a print *,"Hello from foo.bar" print *,"a=",a a = a + 5 print *,"a=",a end subroutine bar end module foo Then with a supported F90 compiler (running `f2py -c --help-compiler' will display the found compilers) f2py will generate an extension module fun.so into the current directory and the Fortran module foo subroutine bar can be called from Python as follows >>> import fun >>> print fun.foo.bar.__doc__ bar - Function signature: bar(a) Required arguments: a : in/output rank-0 array(int,'i') >>> from Numeric import array >>> a = array(3) >>> fun.foo.bar(a) Hello from foo.bar a= 3 a= 8 >>> a 8 >>> This works nicely with all supported Fortran compilers. However, the F compiler (http://www.fortran.com/F/compilers.html) is an exception. Namely, the F compiler is designed to recognize only module procedures (and main programs, of course) but F2PY needs to compile also the so-called external procedures that it generates to facilitate accessing Fortran F90 module procedures from C and subsequently from Python. As a result, wrapping F compiled Fortran procedures to Python is _not_ possible using the simple procedure as described above. But, there is a workaround that I'll describe below in five steps. 1) Compile foo.f90: F -c foo.f90 This creates an object file foo.o into the current directory. 2) Create the signature file: f2py foo.f90 -h foo.pyf This creates a file foo.pyf containing module foo ! in foo.f90 real public :: bar subroutine bar(a) ! in foo.f90:foo integer intent(inout) :: a end subroutine bar end module foo 3) Open the file foo.pyf with your favorite text editor and change the above signature to python module foo interface subroutine bar(a) fortranname foo_MP_bar intent(c) bar integer intent(in,out) :: a end subroutine bar end interface end python module foo The most important modifications are a) adding `python' keyword everywhere before the `module' keyword b) including an `interface' block around the all subroutine blocks. c) specifying the real symbol name of the subroutine using `fortranname' statement. F generated symbol names are in the form <module name>_MP_<subroutine name> d) specifying that subroutine is `intent(c)'. Notice that the `intent(inout)' attribute is changed to `intent(in,out)' that instructs the wrapper to return the modified value of `a'. 4) Build the extension module f2py -c foo.pyf foo.o --fcompiler=Gnu /opt/F/lib/quickfit.o \ /opt/F/lib/libf96.a This will create the extension module foo.so into the current directory. Notice that you must use Gnu compiler (gcc) for linking. And the paths to F specific object files and libraries may differ for your F installation. 5) Finally, we can call the module subroutine `bar' from Python >>> import foo >>> print foo.bar.__doc__ bar - Function signature: a = bar(a) Required arguments: a : input int Return objects: a : int >>> foo.bar(3) 8 >>> Notice that the F compiled module procedures are called as ordinary external procedures. Also I/O seems to be lacking for F compiled Fortran modules. Enjoy, Pearu |