diff options
author | Armin Rigo <arigo@tunes.org> | 2016-04-21 11:45:50 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2016-04-21 11:45:50 +0200 |
commit | 563c42d39808fbb0c572798b87fa356b10aeeb20 (patch) | |
tree | 28bfb10176523467b4961a0817b166d7bb0d4a1a | |
parent | c5e7a23a3bb2c7083390f1498ed9a64dfd51c504 (diff) | |
download | cffi-563c42d39808fbb0c572798b87fa356b10aeeb20.tar.gz |
ffi.unpack(), extern "Python+C"
-rw-r--r-- | doc/source/ref.rst | 48 | ||||
-rw-r--r-- | doc/source/using.rst | 45 | ||||
-rw-r--r-- | doc/source/whatsnew.rst | 20 |
3 files changed, 101 insertions, 12 deletions
diff --git a/doc/source/ref.rst b/doc/source/ref.rst index ea286c4..fd84767 100644 --- a/doc/source/ref.rst +++ b/doc/source/ref.rst @@ -53,6 +53,9 @@ instance of the named C type initialized with the given value. The value is casted between integers or pointers of any type. +.. _ffi-errno: +.. _ffi-getwinerror: + ffi.errno, ffi.getwinerror() ++++++++++++++++++++++++++++ @@ -70,6 +73,9 @@ a message instead of using ``GetLastError()``. function as usual.) +.. _ffi-string: +.. _ffi-unpack: + ffi.string(), ffi.unpack() ++++++++++++++++++++++++++ @@ -78,8 +84,9 @@ string) from the 'cdata'. - If 'cdata' is a pointer or array of characters or bytes, returns the null-terminated string. The returned string extends until the first - null character, or at most 'maxlen' characters. If 'cdata' is an - array then 'maxlen' defaults to its length. See ``ffi.buffer()`` below + null character. The 'maxlen' argument limits how far we look for a + null character. If 'cdata' is an + array then 'maxlen' defaults to its length. See ``ffi.unpack()`` below for a way to continue past the first null character. *Python 3:* this returns a ``bytes``, not a ``str``. @@ -94,8 +101,26 @@ string) from the 'cdata'. If the value is out of range, it is simply returned as the stringified integer. -**ffi.unpack(...)**: XXXXXXXXXXX +**ffi.unpack(cdata, length)**: unpacks an array of C data of the given +length, returning a Python string/unicode/list. The 'cdata' should be +a pointer; if it is an array it is first converted to the pointer +type. *New in version 1.6.* + +- If 'cdata' is a pointer to 'char', returns a byte string. It does + not stop at the first null. (An equivalent way to do that is + ``ffi.buffer(cdata, length)[:]``.) + +- If 'cdata' is a pointer to 'wchar_t', returns a unicode string. + ('length' is measured in number of wchar_t; it is not the size in + bytes.) + +- If 'cdata' is a pointer to anything else, returns a list, of the + given 'length'. (A slower way to do that is ``[cdata[i] for i in + range(length)]``.) + +.. _ffi-buffer: +.. _ffi-from-buffer: ffi.buffer(), ffi.from_buffer() +++++++++++++++++++++++++++++++ @@ -180,6 +205,10 @@ buffer. *New in version 1.3.* Examples: the memory at ``myptr`` to the memory at ``myptr + 1``. +.. _ffi-typeof: +.. _ffi-sizeof: +.. _ffi-alignof: + ffi.typeof(), ffi.sizeof(), ffi.alignof() +++++++++++++++++++++++++++++++++++++++++ @@ -216,6 +245,7 @@ like in the equivalent ``sizeof`` operator in C. the argument. Corresponds to the ``__alignof__`` operator in GCC. +.. _ffi-offsetof: .. _ffi-addressof: ffi.offsetof(), ffi.addressof() @@ -260,6 +290,9 @@ address can be taken, use ``ffi.new("int[1]")`` in the first place; similarly, for a pointer, use ``ffi.new("foo_t *[1]")``. +.. _ffi-cdata: +.. _ffi-ctype: + ffi.CData, ffi.CType ++++++++++++++++++++ @@ -297,6 +330,9 @@ and ``__exit__()`` methods, allocating and freeing the C data at known points in time, and using it in a ``with`` statement. +.. _ffi-new-handle: +.. _ffi-from-handle: + ffi.new_handle(), ffi.from_handle() +++++++++++++++++++++++++++++++++++ @@ -341,6 +377,9 @@ to a global set. It can later be removed from the set by value compares equal. +.. _ffi-dlopen: +.. _ffi-dlclose: + ffi.dlopen(), ffi.dlclose() +++++++++++++++++++++++++++ @@ -428,6 +467,9 @@ example:: .. __: https://bitbucket.org/cffi/cffi/issues/233/ +.. _ffi-getctype: +.. _ffi-list-types: + ffi.getctype(), ffi.list_types() ++++++++++++++++++++++++++++++++ diff --git a/doc/source/using.rst b/doc/source/using.rst index 626970f..933ab6f 100644 --- a/doc/source/using.rst +++ b/doc/source/using.rst @@ -577,12 +577,15 @@ Extern "Python" accessed from C directly In case you want to access some ``extern "Python"`` function directly from the C code written in ``set_source()``, you need to write a -forward static declaration. The real implementation of this function +forward declaration. (By default it needs to be static, but see +`next paragraph`__.) The real implementation of this function is added by CFFI *after* the C code---this is needed because the declaration might use types defined by ``set_source()`` (e.g. ``event_t`` above, from the ``#include``), so it cannot be generated before. +.. __: `extern-python-c`_ + :: ffi.set_source("_demo_cffi", """ @@ -612,6 +615,46 @@ useful if the logic in ``my_algo()`` is much more complex):: } """) +.. _extern-python-c: + +Extern "Python+C" +~~~~~~~~~~~~~~~~~ + +Functions declared with ``extern "Python"`` are generated as +``static`` functions in the C source. However, in some cases it is +convenient to make them non-static, typically when you want to make +them directly callable from other C source files. To do that, you can +say ``extern "Python+C"`` instead of just ``extern "Python"``. *New +in version 1.6.* + ++------------------------------------+--------------------------------------+ +| if the cdef contains | then CFFI generates | ++------------------------------------+--------------------------------------+ +| ``extern "Python" int f(int);`` | ``static int f(int) { /* code */ }`` | ++------------------------------------+--------------------------------------+ +| ``extern "Python+C" int f(int);`` | ``int f(int) { /* code */ }`` | ++------------------------------------+--------------------------------------+ + +The name ``extern "Python+C"`` comes from the fact that we want an +extern function in both senses: as an ``extern "Python"``, and as a +C function that is not static. + +You cannot make CFFI generate additional macros or other +compiler-specific stuff like the GCC ``__attribute__``. You can only +control whether the function should be ``static`` or not. But often, +these attributes must be written alongside the function *header*, and +it is fine if the function *implementation* does not repeat them:: + + ffi.cdef(""" + extern "Python+C" int f(int); /* not static */ + """) + ffi.set_source("_example_cffi", """ + /* the forward declaration, setting a gcc attribute + (this line could also be in some .h file, to be included + both here and in the other C files of the project) */ + int f(int) __attribute__((visibility("hidden"))); + """) + Extern "Python": reference ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst index ad707bc..fa31f14 100644 --- a/doc/source/whatsnew.rst +++ b/doc/source/whatsnew.rst @@ -6,11 +6,11 @@ What's New v1.6 ==== -* ffi.list_types() +* `ffi.list_types()`_ -* ffi.unpack() +* `ffi.unpack()`_ -* extern "Python+C" +* `extern "Python+C"`_ * in API mode, ``lib.foo.__doc__`` contains the C signature now. On CPython you can say ``help(lib.foo)``, but for some reason @@ -18,8 +18,12 @@ v1.6 haven't yet figured out the hacks needed to convince ``pydoc`` to show more. (You can use ``dir(lib)`` but it is not most helpful.) -* Yet another attempt at robustness against CPython's interpreter - shutdown logic +* Yet another attempt at robustness of ``ffi.def_extern()`` against + CPython's interpreter shutdown logic. + +.. _`ffi.list_types()`: ref.html#ffi-list-types +.. _`ffi.unpack()`: ref.html#ffi-unpack +.. _`extern "Python+C"`: using.html#extern-python-c v1.5.2 @@ -101,8 +105,8 @@ v1.4.0 the docs`__ of ``ffi.new_handle()`` has been here since v0.8!) .. __: using.html#extern-python -.. __: ref.html#ffi-initonce -.. __: using.html#ffi-new-handle +.. __: ref.html#ffi-init-once +.. __: ref.html#ffi-new-handle v1.3.1 @@ -212,7 +216,7 @@ v1.2.0 support for `alternative allocators`__. .. __: using.html#callbacks -.. __: ref.html#new-allocator +.. __: ref.html#ffi-new-allocator v1.1.2 |