summaryrefslogtreecommitdiff
path: root/doc/source/f2py
diff options
context:
space:
mode:
authormelissawm <melissawm.github@gmail.com>2021-12-15 12:21:54 -0300
committermelissawm <melissawm.github@gmail.com>2022-01-05 14:13:10 -0300
commit9867da9994a2f0dbfdec412fbb7d77032cb27e42 (patch)
tree05ffb52231adc9dcdcff4f73e9b2ca38278adf00 /doc/source/f2py
parent4a6f65f10ab65307a9e1118f61d3504a7eca9de1 (diff)
downloadnumpy-9867da9994a2f0dbfdec412fbb7d77032cb27e42.tar.gz
Responding to review comments
Diffstat (limited to 'doc/source/f2py')
-rw-r--r--doc/source/f2py/code/add-edited.pyf6
-rw-r--r--doc/source/f2py/code/add-improved.f16
-rw-r--r--doc/source/f2py/code/add.f11
-rw-r--r--doc/source/f2py/code/add.pyf6
-rw-r--r--doc/source/f2py/code/filter.f19
-rw-r--r--doc/source/f2py/code/myroutine-edited.pyf17
-rw-r--r--doc/source/f2py/code/myroutine.f9010
-rw-r--r--doc/source/f2py/code/myroutine.pyf17
-rw-r--r--doc/source/f2py/f2py-examples.rst235
-rw-r--r--doc/source/f2py/f2py.getting-started.rst8
-rw-r--r--doc/source/f2py/signature-file.rst15
11 files changed, 192 insertions, 168 deletions
diff --git a/doc/source/f2py/code/add-edited.pyf b/doc/source/f2py/code/add-edited.pyf
new file mode 100644
index 000000000..a1c375996
--- /dev/null
+++ b/doc/source/f2py/code/add-edited.pyf
@@ -0,0 +1,6 @@
+ subroutine zadd(a,b,c,n) ! in :add:add.f
+ double complex dimension(n) :: a
+ double complex dimension(n) :: b
+ double complex intent(out),dimension(n) :: c
+ integer intent(hide),depend(a) :: n=len(a)
+ end subroutine zadd \ No newline at end of file
diff --git a/doc/source/f2py/code/add-improved.f b/doc/source/f2py/code/add-improved.f
new file mode 100644
index 000000000..f12b6560b
--- /dev/null
+++ b/doc/source/f2py/code/add-improved.f
@@ -0,0 +1,16 @@
+ C
+ SUBROUTINE ZADD(A,B,C,N)
+ C
+ CF2PY INTENT(OUT) :: C
+ CF2PY INTENT(HIDE) :: N
+ CF2PY DOUBLE COMPLEX :: A(N)
+ CF2PY DOUBLE COMPLEX :: B(N)
+ CF2PY DOUBLE COMPLEX :: C(N)
+ DOUBLE COMPLEX A(*)
+ DOUBLE COMPLEX B(*)
+ DOUBLE COMPLEX C(*)
+ INTEGER N
+ DO 20 J = 1, N
+ C(J) = A(J) + B(J)
+ 20 CONTINUE
+ END \ No newline at end of file
diff --git a/doc/source/f2py/code/add.f b/doc/source/f2py/code/add.f
new file mode 100644
index 000000000..c3002fd25
--- /dev/null
+++ b/doc/source/f2py/code/add.f
@@ -0,0 +1,11 @@
+ C
+ SUBROUTINE ZADD(A,B,C,N)
+ C
+ DOUBLE COMPLEX A(*)
+ DOUBLE COMPLEX B(*)
+ DOUBLE COMPLEX C(*)
+ INTEGER N
+ DO 20 J = 1, N
+ C(J) = A(J)+B(J)
+ 20 CONTINUE
+ END
diff --git a/doc/source/f2py/code/add.pyf b/doc/source/f2py/code/add.pyf
new file mode 100644
index 000000000..6a2a8533d
--- /dev/null
+++ b/doc/source/f2py/code/add.pyf
@@ -0,0 +1,6 @@
+ subroutine zadd(a,b,c,n) ! in :add:add.f
+ double complex dimension(*) :: a
+ double complex dimension(*) :: b
+ double complex dimension(*) :: c
+ integer :: n
+ end subroutine zadd \ No newline at end of file
diff --git a/doc/source/f2py/code/filter.f b/doc/source/f2py/code/filter.f
new file mode 100644
index 000000000..a23e2d9b1
--- /dev/null
+++ b/doc/source/f2py/code/filter.f
@@ -0,0 +1,19 @@
+C
+ SUBROUTINE DFILTER2D(A,B,M,N)
+C
+ DOUBLE PRECISION A(M,N)
+ DOUBLE PRECISION B(M,N)
+ INTEGER N, M
+CF2PY INTENT(OUT) :: B
+CF2PY INTENT(HIDE) :: N
+CF2PY INTENT(HIDE) :: M
+ DO 20 I = 2,M-1
+ DO 40 J = 2,N-1
+ B(I,J) = A(I,J) +
+ $ (A(I-1,J)+A(I+1,J) +
+ $ A(I,J-1)+A(I,J+1) )*0.5D0 +
+ $ (A(I-1,J-1) + A(I-1,J+1) +
+ $ A(I+1,J-1) + A(I+1,J+1))*0.25D0
+ 40 CONTINUE
+ 20 CONTINUE
+ END
diff --git a/doc/source/f2py/code/myroutine-edited.pyf b/doc/source/f2py/code/myroutine-edited.pyf
new file mode 100644
index 000000000..c1af805c2
--- /dev/null
+++ b/doc/source/f2py/code/myroutine-edited.pyf
@@ -0,0 +1,17 @@
+ ! -*- f90 -*-
+ ! Note: the context of this file is case sensitive.
+
+ python module myroutine ! in
+ interface ! in :myroutine
+ subroutine s(n,m,c,x) ! in :myroutine:myroutine.f90
+ integer intent(in) :: n
+ integer intent(in) :: m
+ real*8 dimension(:),intent(in) :: c
+ real*8 dimension(n,m),intent(out) :: x
+ end subroutine s
+ end interface
+ end python module myroutine
+
+ ! This file was auto-generated with f2py (version:1.23.0.dev0+120.g4da01f42d).
+ ! See:
+ ! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e \ No newline at end of file
diff --git a/doc/source/f2py/code/myroutine.f90 b/doc/source/f2py/code/myroutine.f90
new file mode 100644
index 000000000..592796a6a
--- /dev/null
+++ b/doc/source/f2py/code/myroutine.f90
@@ -0,0 +1,10 @@
+subroutine s(n, m, c, x)
+ implicit none
+ integer, intent(in) :: n, m
+ real(kind=8), intent(out), dimension(n,m) :: x
+ real(kind=8), intent(in) :: c(:)
+
+ x = 0.0d0
+ x(1, 1) = c(1)
+
+end subroutine s \ No newline at end of file
diff --git a/doc/source/f2py/code/myroutine.pyf b/doc/source/f2py/code/myroutine.pyf
new file mode 100644
index 000000000..0576fb888
--- /dev/null
+++ b/doc/source/f2py/code/myroutine.pyf
@@ -0,0 +1,17 @@
+! -*- f90 -*-
+ ! Note: the context of this file is case sensitive.
+
+ python module myroutine ! in
+ interface ! in :myroutine
+ subroutine s(n,m,c,x) ! in :myroutine:myroutine.f90
+ integer intent(in) :: n
+ integer intent(in) :: m
+ real*8 dimension(:),intent(in) :: c
+ real*8 dimension(n,m),intent(out),depend(m,n) :: x
+ end subroutine s
+ end interface
+ end python module myroutine
+
+ ! This file was auto-generated with f2py (version:1.23.0.dev0+120.g4da01f42d).
+ ! See:
+ ! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e \ No newline at end of file
diff --git a/doc/source/f2py/f2py-examples.rst b/doc/source/f2py/f2py-examples.rst
index bae0a1448..471b0ec59 100644
--- a/doc/source/f2py/f2py-examples.rst
+++ b/doc/source/f2py/f2py-examples.rst
@@ -14,26 +14,15 @@ Creating source for a basic extension module
Consider the following subroutine, contained in a file named :file:`add.f`
-.. code-block:: fortran
-
- C
- SUBROUTINE ZADD(A,B,C,N)
- C
- DOUBLE COMPLEX A(*)
- DOUBLE COMPLEX B(*)
- DOUBLE COMPLEX C(*)
- INTEGER N
- DO 20 J = 1, N
- C(J) = A(J)+B(J)
- 20 CONTINUE
- END
+.. literalinclude:: ./code/add.f
+ :language: fortran
This routine simply adds the elements in two contiguous arrays and places the
result in a third. The memory for all three arrays must be provided by the
calling routine. A very basic interface to this routine can be automatically
generated by f2py::
- f2py -m add add.f
+ python -m numpy.f2py -m add add.f
This command will produce an extension module named :file:`addmodule.c` in the
current directory. This extension module can now be compiled and used from
@@ -42,18 +31,21 @@ Python just like any other extension module.
Creating a compiled extension module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. note::
+
+ This usage depends heavily on ``numpy.distutils``, see :ref:`f2py-bldsys`
+ for more details.
+
You can also get f2py to both compile :file:`add.f` along with the produced
extension module leaving only a shared-library extension file that can
be imported from Python::
- f2py -c -m add add.f
+ python -m numpy.f2py -c -m add add.f
-This command leaves a file named add.{ext} in the current directory
-(where {ext} is the appropriate extension for a Python extension
-module on your platform --- so, pyd, *etc.* ). This module may then be
-imported from Python. It will contain a method for each subroutine in
-add (zadd, cadd, dadd, sadd). The docstring of each method contains
-information about how the module method may be called:
+This command produces a Python extension module compatible with your platform.
+This module may then be imported from Python. It will contain a method for each
+subroutine in ``add``. The docstring of each method contains information about
+how the module method may be called:
.. code-block:: python
@@ -73,55 +65,43 @@ information about how the module method may be called:
Improving the basic interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The default interface is a very literal translation of the Fortran
-code into Python. The Fortran array arguments must now be NumPy arrays
-and the integer argument should be an integer. The interface will
-attempt to convert all arguments to their required types (and shapes)
-and issue an error if unsuccessful. However, because it knows nothing
-about the semantics of the arguments (such that C is an output and n
-should really match the array sizes), it is possible to abuse this
-function in ways that can cause Python to crash. For example:
+The default interface is a very literal translation of the Fortran code into
+Python. The Fortran array arguments are converted to NumPy arrays and the
+integer argument should be mapped to a ``C`` integer. The interface will attempt
+to convert all arguments to their required types (and shapes) and issue an error
+if unsuccessful. However, because ``f2py`` knows nothing about the semantics of
+the arguments (such that ``C`` is an output and ``n`` should really match the
+array sizes), it is possible to abuse this function in ways that can cause
+Python to crash. For example:
.. code-block:: python
>>> add.zadd([1, 2, 3], [1, 2], [3, 4], 1000)
-will cause a program crash on most systems. Under the covers, the
-lists are being converted to proper arrays but then the underlying add
-loop is told to cycle way beyond the borders of the allocated memory.
-
-In order to improve the interface, directives should be provided. This
-is accomplished by constructing an interface definition file. It is
-usually best to start from the interface file that f2py can produce
-(where it gets its default behavior from). To get f2py to generate the
-interface file use the -h option::
+will cause a program crash on most systems. Under the hood, the lists are being
+converted to arrays but then the underlying ``add`` function is told to cycle
+way beyond the borders of the allocated memory.
- f2py -h add.pyf -m add add.f
+In order to improve the interface, ``f2py`` supports directives. This is
+accomplished by constructing a signature file. It is usually best to start from
+the interfaces that ``f2py`` produces in that file, which correspond to the
+default behavior. To get ``f2py`` to generate the interface file use the ``-h``
+option::
-This command leaves the file add.pyf in the current directory. The
-section of this file corresponding to zadd is:
+ python -m numpy.f2py -h add.pyf -m add add.f
-.. code-block:: fortran
+This command creates the ``add.pyf`` file in the current directory. The section
+of this file corresponding to ``zadd`` is:
- subroutine zadd(a,b,c,n) ! in :add:add.f
- double complex dimension(*) :: a
- double complex dimension(*) :: b
- double complex dimension(*) :: c
- integer :: n
- end subroutine zadd
+.. literalinclude:: ./code/add.pyf
+ :language: fortran
-By placing intent directives and checking code, the interface can be
-cleaned up quite a bit until the Python module method is both easier
-to use and more robust.
+By placing intent directives and checking code, the interface can be cleaned up
+quite a bit so the Python module method is both easier to use and more robust to
+malformed inputs.
-.. code-block:: fortran
-
- subroutine zadd(a,b,c,n) ! in :add:add.f
- double complex dimension(n) :: a
- double complex dimension(n) :: b
- double complex intent(out),dimension(n) :: c
- integer intent(hide),depend(a) :: n=len(a)
- end subroutine zadd
+.. literalinclude:: ./code/add-edited.pyf
+ :language: fortran
The intent directive, intent(out) is used to tell f2py that ``c`` is
an output variable and should be created by the interface before being
@@ -135,9 +115,9 @@ created).
After modifying ``add.pyf``, the new Python module file can be generated
by compiling both ``add.f`` and ``add.pyf``::
- f2py -c add.pyf add.f
+ python -m numpy.f2py -c add.pyf add.f
-The new interface has docstring:
+The new interface's docstring is:
.. code-block:: python
@@ -168,32 +148,23 @@ Notice the automatic conversion to the correct format that occurred.
Inserting directives in Fortran source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The nice interface can also be generated automatically by placing the
-variable directives as special comments in the original Fortran code.
+The robust interface of the previous section can also be generated automatically
+by placing the variable directives as special comments in the original Fortran
+code.
+
+.. note::
+
+ For projects where the Fortran code is being actively developed, this may be
+ preferred.
+
Thus, if the source code is modified to contain:
-.. code-block:: fortran
-
- C
- SUBROUTINE ZADD(A,B,C,N)
- C
- CF2PY INTENT(OUT) :: C
- CF2PY INTENT(HIDE) :: N
- CF2PY DOUBLE COMPLEX :: A(N)
- CF2PY DOUBLE COMPLEX :: B(N)
- CF2PY DOUBLE COMPLEX :: C(N)
- DOUBLE COMPLEX A(*)
- DOUBLE COMPLEX B(*)
- DOUBLE COMPLEX C(*)
- INTEGER N
- DO 20 J = 1, N
- C(J) = A(J) + B(J)
- 20 CONTINUE
- END
+.. literalinclude:: ./code/add-improved.f
+ :language: fortran
Then, one can compile the extension module using::
- f2py -c -m add add.f
+ python -m numpy.f2py -c -m add add.f
The resulting signature for the function add.zadd is exactly the same
one that was created previously. If the original source code had
@@ -211,54 +182,28 @@ precision floating-point numbers using a fixed averaging filter. The advantage
of using Fortran to index into multi-dimensional arrays should be clear from
this example.
-.. code-block::
-
- SUBROUTINE DFILTER2D(A,B,M,N)
- C
- DOUBLE PRECISION A(M,N)
- DOUBLE PRECISION B(M,N)
- INTEGER N, M
- CF2PY INTENT(OUT) :: B
- CF2PY INTENT(HIDE) :: N
- CF2PY INTENT(HIDE) :: M
- DO 20 I = 2,M-1
- DO 40 J=2,N-1
- B(I,J) = A(I,J) +
- $ (A(I-1,J)+A(I+1,J) +
- $ A(I,J-1)+A(I,J+1) )*0.5D0 +
- $ (A(I-1,J-1) + A(I-1,J+1) +
- $ A(I+1,J-1) + A(I+1,J+1))*0.25D0
- 40 CONTINUE
- 20 CONTINUE
- END
+.. literalinclude:: ./code/filter.f
+ :language: fortran
This code can be compiled and linked into an extension module named
filter using::
- f2py -c -m filter filter.f
+ python -m numpy.f2py -c -m filter filter.f
This will produce an extension module in the current directory with a method
-named dfilter2d that returns a filtered version of the input.
+named ``dfilter2d`` that returns a filtered version of the input.
``depends`` keyword example
---------------------------
-Consider the following code, saved in the file ``myroutine.f90``::
-
- subroutine s(n, m, c, x)
- implicit none
- integer, intent(in) :: n, m
- real*8, intent(out), dimension(n,m) :: x
- real*8, intent(in) :: c(:)
-
- x = 0.0d0
- x(1, 1) = c(1)
+Consider the following code, saved in the file ``myroutine.f90``:
- end subroutine s
+.. literalinclude:: ./code/myroutine.f90
+ :language: fortran
-Wrapping this with ``f2py -c myroutine.f90 -m myroutine``, we can do the
-following in Python::
+Wrapping this with ``python -m numpy.f2py -c myroutine.f90 -m myroutine``, we
+can do the following in Python::
>>> import numpy as np
>>> import myroutine
@@ -268,58 +213,22 @@ following in Python::
[0., 0., 0.]])
Now, instead of generating the extension module directly, we will create a
-signature file for this subroutine first. This may be a common pattern in
+signature file for this subroutine first. This is a common pattern for
multi-step extension module generation. In this case, after running
-.. code-block::
-
- f2py myroutine.f90 -h myroutine.pyf
-
-the following signature file is generated::
-
- ! -*- f90 -*-
- ! Note: the context of this file is case sensitive.
-
- python module myroutine ! in
- interface ! in :myroutine
- subroutine s(n,m,c,x) ! in :myroutine:myroutine.f90
- integer intent(in) :: n
- integer intent(in) :: m
- real*8 dimension(:),intent(in) :: c
- real*8 dimension(n,m),intent(out),depend(m,n) :: x
- end subroutine s
- end interface
- end python module myroutine
-
- ! This file was auto-generated with f2py (version:1.23.0.dev0+120.g4da01f42d).
- ! See:
- ! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e
-
-
-Now, if we run ``f2py -c myroutine.pyf myroutine.f90`` we see an error; note
-that the signature file included a ``depend(m,n)`` statement for x which is not
-necessary. Indeed, editing the file above to read
-
-.. code-block::
+ python -m numpy.f2py myroutine.f90 -h myroutine.pyf
- ! -*- f90 -*-
- ! Note: the context of this file is case sensitive.
+the following signature file is generated:
- python module myroutine ! in
- interface ! in :myroutine
- subroutine s(n,m,c,x) ! in :myroutine:myroutine.f90
- integer intent(in) :: n
- integer intent(in) :: m
- real*8 dimension(:),intent(in) :: c
- real*8 dimension(n,m),intent(out) :: x
- end subroutine s
- end interface
- end python module myroutine
+.. literalinclude:: ./code/myroutine.pyf
+ :language: fortran
- ! This file was auto-generated with f2py (version:1.23.0.dev0+120.g4da01f42d).
- ! See:
- ! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e
+Now, if we run ``python -m numpy.f2py -c myroutine.pyf myroutine.f90`` we see an
+error; note that the signature file included a ``depend(m,n)`` statement for
+``x`` which is not necessary. Indeed, editing the file above to read
+.. literalinclude:: ./code/myroutine-edited.pyf
+ :language: fortran
and running ``f2py -c myroutine.pyf myroutine.f90`` yields correct results.
diff --git a/doc/source/f2py/f2py.getting-started.rst b/doc/source/f2py/f2py.getting-started.rst
index 9c9d16dab..da88b46f5 100644
--- a/doc/source/f2py/f2py.getting-started.rst
+++ b/doc/source/f2py/f2py.getting-started.rst
@@ -14,7 +14,7 @@ following steps:
needed to create wrapper functions.
* Optionally, F2PY-created signature files can be edited to optimize wrapper
- functions, to make them "smarter" and more "Pythonic".
+ functions, which can make them "smarter" and more "Pythonic".
* F2PY reads a signature file and writes a Python C/API module containing
Fortran/C/Python bindings.
@@ -64,6 +64,12 @@ or, alternatively, if the ``f2py`` command-line tool is available,
f2py -c fib1.f -m fib1
+.. note::
+
+ Because the ``f2py`` command might not be available in all system, notably on
+ Windows, we will use the ``python -m numpy.f2py`` command throughout this
+ guide.
+
This command compiles and wraps ``fib1.f`` (``-c``) to create the extension
module ``fib1.so`` (``-m``) in the current directory. A list of command line
options can be seen by executing ``python -m numpy.f2py``. Now, in Python the
diff --git a/doc/source/f2py/signature-file.rst b/doc/source/f2py/signature-file.rst
index e0c886c13..697b259cd 100644
--- a/doc/source/f2py/signature-file.rst
+++ b/doc/source/f2py/signature-file.rst
@@ -16,6 +16,13 @@ constructs that are irrelevant for creating the interface. However, this also
means that syntax errors are not caught by F2PY and will only be caught when the
library is built.
+.. note::
+
+ Currently, F2PY may fail with valid Fortran constructs, such as intrinsic
+ modules. If this happens, you can check the
+ :ref:`NumPy GitHub issue tracker <https://github.com/numpy/numpy/issues>` for
+ possible workarounds or work-in-progress ideas.
+
In general, the contents of the signature files are case-sensitive. When
scanning Fortran codes to generate a signature file, F2PY lowers all cases
automatically except in multi-line blocks or when the ``--no-lower`` option is
@@ -596,10 +603,10 @@ Extensions
F2PY directives
^^^^^^^^^^^^^^^^
-The F2PY directives allow using F2PY signature file constructs in
-Fortran 77/90 source codes. With this feature one can (almost) completely skip
-the intermediate signature file generation and apply F2PY directly to Fortran
-source codes.
+The F2PY directives allow using F2PY signature file constructs in Fortran 77/90
+source codes. With this feature one can (almost) completely skip the
+intermediate signature file generation and apply F2PY directly to Fortran source
+codes.
F2PY directives have the following form::