[pypy-commit] cffi default: Working with pointers, structures and arrays.

arigo noreply at buildbot.pypy.org
Thu Jun 14 21:19:48 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r352:a263e4103eab
Date: 2012-06-14 21:19 +0200
http://bitbucket.org/cffi/cffi/changeset/a263e4103eab/

Log:	Working with pointers, structures and arrays.

diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -285,6 +285,10 @@
  * unknown types: the syntax ``typedef ... foo_t;`` declares the type
    ``foo_t`` as opaque.
 
+ * array lengths: when used as structure fields, arrays can have an
+   unspecified length, as in ``int n[];``.  The length is completed
+   by the C compiler.
+
  * 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
@@ -294,7 +298,79 @@
 Working with pointers, structures and arrays
 --------------------------------------------
 
+The C code's integers and floating-point values are mapped to Python's
+regular ``int``, ``long`` and ``float``.  Moreover, the C type ``char``
+correspond to single-character strings in Python.  (If you want it to
+map to small integers, use either ``signed char`` or ``unsigned char``.)
 
+Pointers, structures and arrays are more complex: they don't have an
+obvious Python equivalent.  They correspond to objects of type
+``cdata``, which are printed for example as ``<cdata 'struct foo_s *'>``.
+
+``ffi.new(ctype [, initializer])``: this function builds a new cdata
+object of the given ``ctype``.  The ctype is usually some constant
+string describing the C type.  This is similar to a malloc: it allocates
+the memory needed to store an object of the given C type, and returns a
+pointer to it.  Unlike C, the returned pointer object has *ownership* on
+the allocated memory: when this exact object is garbage-collected, then
+the memory is freed.
+
+The memory is initially filled with zeros.  An initializer can be given
+too, as described later.
+
+The cdata objects support mostly the same operations as in C: you can
+read or write from pointers, arrays and structures.  Dereferencing a
+pointer is done usually in C with the syntax ``*p``, which is not valid
+Python, so instead you have to use the alternative syntax ``p[0]``
+(which is also valid C).  Additionally, the ``p->x`` syntax in C becomes
+``p.x`` in Python.
+
+Any operation that would in C return a pointer or array or struct type
+gives you a new cdata object.  Unlike the "original" one, these new
+cdata objects don't have ownership: they are merely references to
+existing memory.
+
+Example::
+
+    ffi.cdef("void somefunction(int *);")
+    lib = ffi.verify("#include <foo.h>")
+
+    x = ffi.new("int")        # allocate one int, and return a pointer to it
+    x[0] = 42                 # fill it
+    lib.somefunction(x)       # call the C function
+    print x[0]                # read the possibly-changed value
+
+The initializer given in ``ffi.new()`` can be mostly anything that you
+would use as an initializer for C code, with lists or tuples instead of
+using the C syntax ``{ .., .., .. }``.  And like C, arrays of chars can
+also be initialized from a string, in which case a terminating null
+character is appended implicitly.  Example::
+
+    typedef struct { int x, y; } foo_t;
+
+    static foo_t globvar = { 1, 2 };     // C syntax
+    globvar = ffi.new("foo_t", [1, 2])   # CFFI equivalent
+
+    static foo_t globvar = { .y=1, .x=2 };        // C syntax
+    globvar = ffi.new("foo_t", {'y': 1, 'x': 2})  # CFFI equivalent
+
+The C array types can have their length unspecified in C types, as long
+as their length can be derived from the initializer, like in C::
+
+    static int globvar[] = { 1, 2, 3, 4 };    // C syntax
+    globvar = ffi.new("int[]", [1, 2, 3, 4])  # CFFI equivalent
+
+As an extension, the initializer can also be just a number, giving
+the length (in case you just want zero-initialization)::
+
+    static int globvar[1000];           // C syntax
+    globvar = ffi.new("int[1000]")      # CFFI 1st equivalent
+    globvar = ffi.new("int[]", 1000)    # CFFI 2nd equivalent
+
+This is useful if the length is not actually a constant, to avoid doing
+things like ``ffi.new("int[%d]" % x)``, which is not recommended:
+``ffi`` normally caches the string ``"int[]"`` to not need to re-parse
+it all the time.
 
 
 


More information about the pypy-commit mailing list