summaryrefslogtreecommitdiff
path: root/doc/source/overview.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/overview.rst')
-rw-r--r--doc/source/overview.rst72
1 files changed, 36 insertions, 36 deletions
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
index bcc5663..dbc3540 100644
--- a/doc/source/overview.rst
+++ b/doc/source/overview.rst
@@ -3,7 +3,7 @@ Overview
=======================================================
.. contents::
-
+
The first section presents a simple working
example of using CFFI to call a C function in a compiled shared object
@@ -61,9 +61,9 @@ Create the file ``piapprox_build.py``:
Execute this script. If everything is OK, it should produce
``_pi_cffi.c``, and then invoke the compiler on it. The produced
-``_pi_cffi.c`` contains a copy of the string given in ``set_source()``,
+``_pi_cffi.c`` contains a copy of the string given in :ref:`set_source() <set_source>`,
in this example the ``#include "pi.h"``. Afterwards, it contains glue code
-for all the functions, types and globals declared in the ``cdef()`` above.
+for all the functions, types and globals declared in the :ref:`cdef() <cdef>` above.
At runtime, you use the extension module like this:
@@ -126,7 +126,7 @@ May look familiar to those who have used ctypes_.
>>> ffi = FFI()
>>> ffi.cdef("""
... int printf(const char *format, ...); // copy-pasted from the man page
- ... """)
+ ... """)
>>> C = ffi.dlopen(None) # loads the entire C namespace
>>> arg = ffi.new("char[]", b"world") # equivalent to C code: char arg[] = "world";
>>> C.printf(b"hi there, %s.\n", arg) # call printf
@@ -138,7 +138,7 @@ Note that ``char *`` arguments expect a ``bytes`` object. If you have a
``str`` (or a ``unicode`` on Python 2) you need to encode it explicitly
with ``somestring.encode(myencoding)``.
-*Python 3 on Windows:* ``ffi.dlopen(None)`` does not work. This problem
+*Python 3 on Windows:* :ref:`ffi.dlopen(None) <dlopen>` does not work. This problem
is messy and not really fixable. The problem does not occur if you try
to call a function from a specific DLL that exists on your system: then
you use ``ffi.dlopen("path.dll")``.
@@ -179,7 +179,7 @@ Struct/Array Example (minimal, in-line)
f.close()
This can be used as a more flexible replacement of the struct_ and
-array_ modules, and replaces ctypes_. You could also call ``ffi.new("pixel_t[600][800]")``
+array_ modules, and replaces ctypes_. You could also call :ref:`ffi.new("pixel_t[600][800]") <new>`
and get a two-dimensional array.
.. _struct: http://docs.python.org/library/struct.html
@@ -191,7 +191,7 @@ and get a two-dimensional array.
This example also admits an out-of-line equivalent. It is similar to
the first example `Main mode of usage`_ above,
but passing ``None`` as the second argument to
-``ffibuilder.set_source()``. Then in the main program you write
+:ref:`ffibuilder.set_source() <set_source>`. Then in the main program you write
``from _simple_example import ffi`` and then the same content as the
in-line example above starting from the line ``image =
ffi.new("pixel_t[]", 800*600)``.
@@ -244,7 +244,7 @@ You need to run the ``example_build.py`` script once to generate
"source code" into the file ``_example.c`` and compile this to a
regular C extension module. (CFFI selects either Python or C for the
module to generate based on whether the second argument to
-``set_source()`` is ``None`` or not.)
+:ref:`set_source() <set_source>` is ``None`` or not.)
*You need a C compiler for this single step. It produces a file called
e.g. _example.so or _example.pyd. If needed, it can be distributed in
@@ -265,7 +265,7 @@ Note that this works independently of the exact C layout of ``struct
passwd`` (it is "API level", as opposed to "ABI level"). It requires
a C compiler in order to run ``example_build.py``, but it is much more
portable than trying to get the details of the fields of ``struct
-passwd`` exactly right. Similarly, in the ``cdef()`` we declared
+passwd`` exactly right. Similarly, in the :ref:`cdef() <cdef>` we declared
``getpwuid()`` as taking an ``int`` argument; on some platforms this
might be slightly incorrect---but it does not matter.
@@ -301,28 +301,28 @@ with the files ``pi.c`` and ``pi.h``:
/* filename: pi.c*/
# include <stdlib.h>
# include <math.h>
-
+
/* Returns a very crude approximation of Pi
given a int: a number of iteration */
float pi_approx(int n){
-
+
double i,x,y,sum=0;
-
+
for(i=0;i<n;i++){
-
+
x=rand();
y=rand();
-
+
if (sqrt(x*x+y*y) < sqrt((double)RAND_MAX*RAND_MAX))
sum++; }
-
+
return 4*(float)sum/(float)n; }
.. code-block:: C
/* filename: pi.h*/
float pi_approx(int n);
-
+
Create a script named ``pi_extension_build.py``, building
the C extension:
@@ -330,21 +330,21 @@ the C extension:
from cffi import FFI
ffibuilder = FFI()
-
+
ffibuilder.cdef("float pi_approx(int n);")
-
+
ffibuilder.set_source("_pi", # name of the output C extension
"""
- #include "pi.h"',
+ #include "pi.h"
""",
sources=['pi.c'], # includes pi.c as additional sources
libraries=['m']) # on Unix, link with the math library
-
+
if __name__ == "__main__":
ffibuilder.compile(verbose=True)
Build the extension:
-
+
.. code-block:: shell
python pi_extension_build.py
@@ -354,14 +354,14 @@ Observe, in the working directory, the generated output files:
Linux for example). It can be called from Python:
.. code-block:: python
-
+
from _pi.lib import pi_approx
-
+
approx = pi_approx(10)
- assert str(pi_approximation).startswith("3.")
-
+ assert str(approx).startswith("3.")
+
approx = pi_approx(10000)
- assert str(approx).startswith("3.1")
+ assert str(approx).startswith("3.1")
.. _performance:
@@ -428,7 +428,7 @@ easily).
This mixture mode lets you massively reduces the import times, because
it is slow to parse a large C header. It also allows you to do more
detailed checkings during build-time without worrying about performance
-(e.g. calling ``cdef()`` many times with small pieces of declarations,
+(e.g. calling :ref:`cdef() <cdef>` many times with small pieces of declarations,
based on the version of libraries detected on the system).
.. code-block:: python
@@ -461,7 +461,7 @@ any more:
lib.printf(b"hi there, number %d\n", ffi.cast("int", 2))
-Note that this ``ffi.dlopen()``, unlike the one from in-line mode,
+Note that this :ref:`ffi.dlopen() <dlopen>`, unlike the one from in-line mode,
does not invoke any additional magic to locate the library: it must be
a path name (with or without a directory), as required by the C
``dlopen()`` or ``LoadLibrary()`` functions. This means that
@@ -496,7 +496,7 @@ In-line, API level
The "API level + in-line" mode combination exists but is long
deprecated. It used to be done with ``lib = ffi.verify("C header")``.
-The out-of-line variant with ``set_source("modname", "C header")`` is
+The out-of-line variant with :ref:`set_source("modname", "C header") <set_source>` is
preferred and avoids a number of problems when the project grows in
size.
@@ -558,13 +558,13 @@ means that most of the documentation or examples can be copied straight
from the man pages.
The declarations can contain **types, functions, constants**
-and **global variables.** What you pass to the ``cdef()`` must not
+and **global variables.** What you pass to the :ref:`cdef() <cdef>` must not
contain more than that; in particular, ``#ifdef`` or ``#include``
directives are not supported. The cdef in the above examples are just
that - they declared "there is a function in the C level with this
given signature", or "there is a struct type with this shape".
-In the ABI examples, the ``dlopen()`` calls load libraries manually.
+In the ABI examples, the :ref:`dlopen() <dlopen>` calls load libraries manually.
At the binary level, a program is split into multiple namespaces---a
global one (on some platforms), plus one namespace per library. So
``dlopen()`` returns a ``<FFILibrary>`` object, and this object has
@@ -576,13 +576,13 @@ you would call ``cdef()`` only once but ``dlopen()`` several times.
By opposition, the API mode works more closely like a C program: the C
linker (static or dynamic) is responsible for finding any symbol used.
You name the libraries in the ``libraries`` keyword argument to
-``set_source()``, but never need to say which symbol comes
+:ref:`set_source() <set_source>`, but never need to say which symbol comes
from which library.
Other common arguments to ``set_source()`` include ``library_dirs`` and
``include_dirs``; all these arguments are passed to the standard
distutils/setuptools.
-The ``ffi.new()`` lines allocate C objects. They are filled
+The :ref:`ffi.new() <new>` lines allocate C objects. They are filled
with zeroes initially, unless the optional second argument is used.
If specified, this argument gives an "initializer", like you can use
with C code to initialize global variables.
@@ -609,10 +609,10 @@ The more fundamental reason to prefer the API mode is that *the C
libraries are typically meant to be used with a C compiler.* You are not
supposed to do things like guess where fields are in the structures.
The "real example" above shows how CFFI uses a C compiler under the
-hood: this example uses ``set_source(..., "C source...")`` and never
-``dlopen()``. When using this approach,
+hood: this example uses :ref:`set_source(..., "C source...") <set_source>` and never
+:ref:`dlopen() <dlopen>`. When using this approach,
we have the advantage that we can use literally "``...``" at various places in
-the ``cdef()``, and the missing information will be completed with the
+the :ref:`cdef() <cdef>`, and the missing information will be completed with the
help of the C compiler. CFFI will turn this into a single C source file,
which contains the "C source" part unmodified, followed by some
"magic" C code and declarations derived from the ``cdef()``. When