[pypy-commit] cffi default: Start writing the Reference section.
arigo
noreply at buildbot.pypy.org
Thu Jun 14 20:44:13 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r351:42090ef917db
Date: 2012-06-14 20:44 +0200
http://bitbucket.org/cffi/cffi/changeset/42090ef917db/
Log: Start writing the Reference section.
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -184,7 +184,7 @@
self._cached_btypes[type] = BType
return BType
- def verify(self, preamble='', **kwargs):
+ def verify(self, source='', **kwargs):
"""Verify that the current ffi signatures compile on this
machine, and return a dynamic library object. The dynamic
library can be used to call functions and access global
@@ -194,7 +194,7 @@
which requires binary compatibility in the signatures.
"""
from .verifier import Verifier
- return Verifier(self).verify(preamble, **kwargs)
+ return Verifier(self).verify(source, **kwargs)
def _make_ffi_library(ffi, libname):
name = libname
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -36,6 +36,31 @@
.. _`ctypes`: http://docs.python.org/library/ctypes.html
+Installation and Status
+=======================================================
+
+This code has been tested on Linux only. It is known to contain
+some cross-platform issues. Work on Windows will be coming soon.
+
+Requirements:
+
+ * Python 2.6 or 2.7
+
+ * pycparser 2.06: http://code.google.com/p/pycparser/
+
+Installation as usual:
+
+ * ``python setup.py install``
+
+ * or you can directly import and use ``cffi``, but if you don't
+ compile the ``_ffi_backend`` extension module, it will fall back
+ to using internally ``ctypes`` (slower).
+
+
+Examples
+=======================================================
+
+
Simple example (ABI level)
--------------------------
@@ -70,7 +95,8 @@
#include <sys/types.h>
#include <pwd.h>
""")
- assert str(C.getpwuid(0).pw_name) == 'root'
+ p = C.getpwuid(0)
+ assert str(p.pw_name) == 'root'
Note that the above example works independently of the exact layout of
``struct passwd``, but so far require a C compiler at runtime. (We plan
@@ -101,41 +127,180 @@
.. _array: http://docs.python.org/library/array.html
-What has actually happened?
----------------------------
+What actually happened?
+-----------------------
-CFFI interface operates on the same level as C - you declare types and functions
-pretty much the same way you would define them in C. In fact most of the examples
-from manpages can be copied without changes.
+The CFFI interface operates on the same level as C - you declare types
+and functions using the same syntax as you would define them in C. This
+means that most of the documentation or examples can be copied straight
+from the man pages.
-The declarations can contain types, functions and global variables.
-The cdef in the above example is just that -
-it declared "there is a function in the C level with a given signature".
+The declarations can contain types, functions and global variables. 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".
-The next line loads libraries. C has multiple namespaces - a global one and local
-ones per library. In this example we load the global one (None as argument to dlopen)
-which always contains the standard C library.
+The ``dlopen()`` line loads libraries. C has multiple namespaces - a
+global one and local ones per library. In this example we load the
+global one (``None`` as argument to ``dlopen()``) which always contains
+the standard C library. You get as a result a ``<FFILibrary>`` object
+that has as attributes all symbols declared in the ``cdef()`` and coming
+from this library.
-Next line is allocating new char[] object and then calling the printf. Simple, isn't it?
+The ``verify()`` line in the second example is an alternative: instead
+of doing a ``dlopen``, it generates and compiles a piece of C code.
+When using ``verify()`` you have the advantage that you can use ``...``
+at various places in the ``cdef()``, and the missing information will
+be completed with the help of the C compiler. It also does checking,
+to verify that your declarations are correct. If the C compiler gives
+warnings or errors, they are reported here.
+
+Finally, the ``ffi.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.
+
+The actual function calls should be obvious.
+
+
+
+Reference
+=======================================================
+
+As a guideline: you have already seen in the above examples all the
+major pieces except maybe ``ffi.cast()``. The rest of this
+documentation gives a more complete reference.
+
Declaring types and functions
-----------------------------
-There is not much to say here
+``ffi.cdef(source)`` parses the given C source. This should be done
+first. It registers all the functions, types, and global variables in
+the C source. The types can be used immediately in 'ffi.new()' and
+other functions. Before you can access the functions and global
+variables, you need to give ``ffi`` another piece of information: where
+they actually come from (which you do with either ``ffi.dlopen()`` or
+``ffi.verify()``).
+
+The C source is parsed internally (using ``pycparser``). This code
+cannot contain ``#include``. It should typically be a self-contained
+piece of declarations extracted from a man page. The only things it
+can assume to exist are the standard types:
+
+ * char, short, int, long, long long (both signed and unsigned)
+
+ * float, double
+
+ * intN_t, uintN_t (for N=8,16,32,64), intptr_t, uintptr_t, ptrdiff_t,
+ size_t, ssize_t
+
+As we will see on `the verification step`_ below, the declarations
+can also contain ``...`` at various places as placeholders that are
+completed only by during a call to ``verify()``.
+
Loading libraries
-----------------
+``ffi.dlopen(libpath)``: this function opens a shared library and
+returns a module-like library object. You can use the library object to
+call the functions previously declared by ``ffi.cdef()``, and to read or
+write global variables. Note that you can use a single ``cdef()`` to
+declare functions from multiple libraries, as long as you load each of
+them with ``dlopen()`` and access the functions from the correct one.
+
+The ``libpath`` is the file name of the shared library, which can
+contain a full path or not (in which case it is searched in standard
+locations, as described in ``man dlopen``). Alternatively, if
+``libpath`` is None, it returns the standard C library (which can be
+used to access the functions of glibc, on Linux).
+
+This gives ABI-level access to the library: you need to have all types
+declared manually exactly as they were while the library was made. No
+checking is done. For this reason, we recommend to use ``ffi.verify()``
+instead when possible.
+
+Note that only functions and global variables are in library objects;
+types exist in the ``ffi`` instance independently of library objects.
+This is due to the C model: the types you declare in C are not tied to a
+particular library, as long as you ``#include`` their headers; but you
+cannot call functions from a library without linking it in your program.
+
+
+The verification step
+---------------------
+
+``ffi.verify(source, ...)``: verifies that the current ffi signatures
+compile on this machine, and return a dynamic library object. The
+dynamic library can be used to call functions and access global
+variables declared by a previous 'ffi.cdef()'. The library is compiled
+by the C compiler: it gives you C-level API compatibility (including
+calling macros, as long as you declared them as functions in
+``ffi.cdef()``). This differs from ``ffi.dlopen()``, which requires
+ABI-level compatibility and must be called several times to open several
+shared libraries.
+
+On top of CPython, the new library is actually a CPython C extension
+module. This solution constrains you to have a C compiler (future work
+will cache the compiled C code and let you distribute it to other
+systems which don't have a C compiler).
+
+The arguments to ``ffi.verify()`` are:
+
+ * ``source``: C code that is pasted verbatim in the generated code (it
+ is *not* parsed internally). It should contain at least the
+ necessary ``#include``. It can also contain the complete
+ implementation of some functions declared in ``cdef()``; this is
+ useful if you really need to write a piece of C code, e.g. to access
+ some advanced macros.
+
+ * ``include_dirs``, ``define_macros``, ``undef_macros``, ``libraries``,
+ ``library_dirs``, ``extra_objects``, ``extra_compile_args``,
+ ``extra_link_args`` (keyword arguments): these are used when
+ compiling the C code, and are passed directly to distutils_.
+
+.. _distutils: http://docs.python.org/distutils/setupscript.html#describing-extension-modules
+
+On the plus side, this solution gives more "C-like" flexibility:
+
+ * functions taking or returning integer or float-point arguments can be
+ misdeclared: if e.g. a function is declared by ``cdef()`` as taking a
+ ``int``, but actually takes a ``long``, then the C compiler handles the
+ difference.
+
+ * other arguments are checked: you get a compilation warning or error
+ if you pass a ``int *`` argument to a function expecting a ``long *``.
+
+Moreover, you can use ``...`` in the following places in the ``cdef()``
+for leaving details unspecified (filled in by the C compiler):
+
+ * structure declarations: any ``struct`` that ends with ``...;`` is
+ partial. It will be completed by the compiler. (You can only access
+ fields that you declared; the compiler can only consider the missing
+ fields as padding.) Any ``struct`` declaration without ``...;`` is
+ assumed to be exact, but this is checked: you get a
+ ``VerificationError`` if it is not.
+
+ * unknown types: the syntax ``typedef ... foo_t;`` declares the type
+ ``foo_t`` as opaque.
+
+ * enums: in ``enum foo { A, B, C, ... };``, the enumerated values are
+ not necessarily in order; the C compiler will reorder them as needed
+ and skip any unmentioned value. Like with structs, an ``enum`` that
+ does not end in ``...`` is assumed to be exact, and this is checked.
+
+
Working with pointers, structures and arrays
--------------------------------------------
-The verification step
----------------------
+
+
+
Indices and tables
==================
* :ref:`genindex`
-* :ref:`modindex`
* :ref:`search`
More information about the pypy-commit
mailing list