[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