Author: Armin Rigo <[email protected]> Branch: Changeset: r2721:338244197c0d Date: 2016-06-20 16:36 +0200 http://bitbucket.org/cffi/cffi/changeset/338244197c0d/
Log: hg merge release-1.7 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/installation.rst b/doc/source/installation.rst --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -53,9 +53,11 @@ * http://pypi.python.org/packages/source/c/cffi/cffi-1.7.0.tar.gz - - MD5: ... + - MD5: 34122a545060cee58bab88feab57006d - - SHA: ... + - SHA: d8033f34e17c0c51bb834b27f6e8c59fc24ae72c + + - SHA256: 6ed5dd6afd8361f34819c68aaebf9e8fc12b5a5893f91f50c9e50c8886bb60df * Or grab the most current version from the `Bitbucket page`_: ``hg clone https://bitbucket.org/cffi/cffi`` 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()``, _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
