summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2016-04-21 11:45:50 +0200
committerArmin Rigo <arigo@tunes.org>2016-04-21 11:45:50 +0200
commit563c42d39808fbb0c572798b87fa356b10aeeb20 (patch)
tree28bfb10176523467b4961a0817b166d7bb0d4a1a
parentc5e7a23a3bb2c7083390f1498ed9a64dfd51c504 (diff)
downloadcffi-563c42d39808fbb0c572798b87fa356b10aeeb20.tar.gz
ffi.unpack(), extern "Python+C"
-rw-r--r--doc/source/ref.rst48
-rw-r--r--doc/source/using.rst45
-rw-r--r--doc/source/whatsnew.rst20
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