[pypy-commit] cffi release-1.7: Doc tweaks

arigo pypy.commits at gmail.com
Mon Jun 20 10:33:31 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: release-1.7
Changeset: r2719:52f417ae8d67
Date: 2016-06-20 16:17 +0200
http://bitbucket.org/cffi/cffi/changeset/52f417ae8d67/

Log:	Doc tweaks

diff --git a/doc/source/cdef.rst b/doc/source/cdef.rst
--- a/doc/source/cdef.rst
+++ b/doc/source/cdef.rst
@@ -636,6 +636,15 @@
 variables defined as dynamic macros (``#define myvar  (*fetchme())``).
 Before version 1.2, you need to write getter/setter functions.
 
+Note that if you declare a variable in ``cdef()`` without using
+``const``, CFFI assumes it is a read-write variable and generates two
+pieces of code, one to read it and one to write it.  If the variable
+cannot in fact be written to in C code, for one reason or another, it
+will not compile.  In this case, you can declare it as a constant: for
+example, instead of ``foo_t *myglob;`` you would use ``foo_t *const
+myglob;``.  Note also that ``const foo_t *myglob;``  is a *variable;* it
+contains a variable pointer to a constant ``foo_t``.
+
 
 Debugging dlopen'ed C libraries
 -------------------------------
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
--- a/doc/source/overview.rst
+++ b/doc/source/overview.rst
@@ -44,81 +44,14 @@
 arguments.  In the above example it would be ``b"world"`` and ``b"hi
 there, %s!\n"``.  In general it is ``somestring.encode(myencoding)``.
 
-*This example does not call any C compiler.*
+*This example does not call any C compiler.  It works in the so-called
+ABI mode, which means that it will crash if you call some function or
+access some fields of a structure that was slightly misdeclared in the
+cdef().*
 
-
-.. _out-of-line-abi-level:
-
-Out-of-line example (ABI level, out-of-line)
---------------------------------------------
-
-In a real program, you would not include the ``ffi.cdef()`` in your
-main program's modules.  Instead, you can rewrite it as follows.  It
-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, based
-on the version of libraries detected on the system).
-
-*This example does not call any C compiler.*
-
-.. code-block:: python
-
-    # file "simple_example_build.py"
-
-    # Note: we instantiate the same 'cffi.FFI' class as in the previous
-    # example, but call the result 'ffibuilder' now instead of 'ffi';
-    # this is to avoid confusion with the other 'ffi' object you get below
-
-    from cffi import FFI
-
-    ffibuilder = FFI()
-    ffibuilder.set_source("_simple_example", None)
-    ffibuilder.cdef("""
-        int printf(const char *format, ...);
-    """)
-
-    if __name__ == "__main__":
-        ffibuilder.compile(verbose=True)
-
-Running it once produces ``_simple_example.py``.  Your main program
-only imports this generated module, not ``simple_example_build.py``
-any more:
-
-.. code-block:: python
-
-    from _simple_example import ffi
-
-    lib = ffi.dlopen(None)      # Unix: open the standard C library
-    #import ctypes.util         # or, try this on Windows:
-    #lib = ffi.dlopen(ctypes.util.find_library("c"))
-
-    lib.printf(b"hi there, number %d\n", ffi.cast("int", 2))
-
-Note that this ``ffi.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
-``ffi.dlopen("libfoo.so")`` is ok, but ``ffi.dlopen("foo")`` is not.
-In the latter case, you could replace it with
-``ffi.dlopen(ctypes.util.find_library("foo"))``.  Also, None is only
-recognized on Unix to open the standard C library.
-
-For distribution purposes, remember that there is a new
-``_simple_example.py`` file generated.  You can either include it
-statically within your project's source files, or, with Setuptools,
-you can say in the ``setup.py``:
-
-.. code-block:: python
-
-    from setuptools import setup
-
-    setup(
-        ...
-        setup_requires=["cffi>=1.0.0"],
-        cffi_modules=["simple_example_build.py:ffibuilder"],
-        install_requires=["cffi>=1.0.0"],
-    )
+If using a C compiler to install your module is an option, it is highly
+recommended to use the API mode described in the next paragraph.  (It is
+also a bit faster at runtime.)
 
 
 .. _out-of-line-api-level:
@@ -131,6 +64,10 @@
 
     # file "example_build.py"
 
+    # Note: we instantiate the same 'cffi.FFI' class as in the previous
+    # example, but call the result 'ffibuilder' now instead of 'ffi';
+    # this is to avoid confusion with the other 'ffi' object you get below
+
     from cffi import FFI
     ffibuilder = FFI()
 
@@ -230,11 +167,11 @@
 *This example does not call any C compiler.*
 
 This example also admits an out-of-line equivalent.  It is similar to
-`Out-of-line example (ABI level, out-of-line)`_ above, but without any
-call to ``ffi.dlopen()``.  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)``.
+`Real example (API level, out-of-line)`_ above, but passing ``None`` as
+the second argument to ``ffibuilder.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)``.
 
 
 .. _performance:
@@ -288,6 +225,77 @@
 distributed in precompiled form like any other extension module.*
 
 
+.. _out-of-line-abi-level:
+
+Out-of-line, ABI level
+----------------------
+
+The out-of-line ABI mode is a mixture of the regular (API) out-of-line
+mode and the in-line ABI mode.  It lets you use the ABI mode, with its
+advantages (not requiring a C compiler) and problems (crashes more
+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,
+based on the version of libraries detected on the system).
+
+.. code-block:: python
+
+    # file "simple_example_build.py"
+
+    from cffi import FFI
+
+    ffibuilder = FFI()
+    ffibuilder.set_source("_simple_example", None)
+    ffibuilder.cdef("""
+        int printf(const char *format, ...);
+    """)
+
+    if __name__ == "__main__":
+        ffibuilder.compile(verbose=True)
+
+Running it once produces ``_simple_example.py``.  Your main program
+only imports this generated module, not ``simple_example_build.py``
+any more:
+
+.. code-block:: python
+
+    from _simple_example import ffi
+
+    lib = ffi.dlopen(None)      # Unix: open the standard C library
+    #import ctypes.util         # or, try this on Windows:
+    #lib = ffi.dlopen(ctypes.util.find_library("c"))
+
+    lib.printf(b"hi there, number %d\n", ffi.cast("int", 2))
+
+Note that this ``ffi.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
+``ffi.dlopen("libfoo.so")`` is ok, but ``ffi.dlopen("foo")`` is not.
+In the latter case, you could replace it with
+``ffi.dlopen(ctypes.util.find_library("foo"))``.  Also, None is only
+recognized on Unix to open the standard C library.
+
+For distribution purposes, remember that there is a new
+``_simple_example.py`` file generated.  You can either include it
+statically within your project's source files, or, with Setuptools,
+you can say in the ``setup.py``:
+
+.. code-block:: python
+
+    from setuptools import setup
+
+    setup(
+        ...
+        setup_requires=["cffi>=1.0.0"],
+        cffi_modules=["simple_example_build.py:ffibuilder"],
+        install_requires=["cffi>=1.0.0"],
+    )
+
+
 .. _embedding:
 
 Embedding
@@ -418,18 +426,18 @@
 functions.)
 
 The generated piece of C code should be the same independently on the
-platform on which you run it (or the Python version),
-so in simple cases you can directly
-distribute the pre-generated C code and treat it as a regular C
-extension module.  The special Setuptools lines in the `example
+platform on which you run it (or the Python version), so in simple cases
+you can directly distribute the pre-generated C code and treat it as a
+regular C extension module (which depends on the ``_cffi_backend``
+module, on CPython).  The special Setuptools lines in the `example
 above`__ are meant for the more complicated cases where we need to
 regenerate the C sources as well---e.g. because the Python script that
-regenerates this file will itself look around the system to know what
-it should include or not.
+regenerates this file will itself look around the system to know what it
+should include or not.
 
 .. __: real-example_
 
-Note that the "API level + in-line" mode combination is deprecated.
-It used to be done with ``lib = ffi.verify("C header")``.  The
-out-of-line variant with ``set_source("modname", "C header")`` is
+Note that 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
 preferred.
diff --git a/doc/source/using.rst b/doc/source/using.rst
--- a/doc/source/using.rst
+++ b/doc/source/using.rst
@@ -537,7 +537,7 @@
             lib.event_cb_register(lib.my_event_callback, userdata)
 
         def process_event(self, evt):
-            ...
+            print "got event!"
 
     @ffi.def_extern()
     def my_event_callback(evt, userdata):
@@ -566,7 +566,7 @@
             lib.event_cb_register(ll_widget, lib.my_event_callback)
 
         def process_event(self, evt):
-            ...
+            print "got event!"
 
     @ffi.def_extern()
     def my_event_callback(ll_widget, evt):
@@ -789,7 +789,7 @@
             lib.register_stuff_with_callback_and_voidp_arg(my_global_callback, handle)
 
         def some_method(self, x):
-            ...
+            print "method called!"
 
 (See also the section about `extern "Python"`_ above, where the same
 general style is used.)
@@ -881,7 +881,7 @@
 
 ``__cdecl`` is supported but is always the default so it can be left
 out.  In the ``cdef()``, you can also use ``WINAPI`` as equivalent to
-``__stdcall``.  As mentioned above, it is not needed (but doesn't
+``__stdcall``.  As mentioned above, it is mostly not needed (but doesn't
 hurt) to say ``WINAPI`` or ``__stdcall`` when declaring a plain
 function in the ``cdef()``.  (The difference can still be seen if you
 take explicitly a pointer to this function with ``ffi.addressof()``,


More information about the pypy-commit mailing list