Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r570:71f5e672a341 Date: 2012-06-29 16:52 +0200 http://bitbucket.org/cffi/cffi/changeset/71f5e672a341/
Log: Documentation updates diff --git a/doc/source/index.rst b/doc/source/index.rst --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -242,7 +242,7 @@ size_t, ssize_t As we will see on `the verification step`_ below, the declarations can -also contain "``...``" at various places; there are placeholders that will +also contain "``...``" at various places; these are placeholders that will be completed by a call to ``verify()``. @@ -250,11 +250,14 @@ ----------------- ``ffi.dlopen(libpath)``: this function opens a shared library and -returns a module-like library object. You can use the library object to -call the functions previously declared by ``ffi.cdef()``, and to read or -write global variables. Note that you can use a single ``cdef()`` to -declare functions from multiple libraries, as long as you load each of -them with ``dlopen()`` and access the functions from the correct one. +returns a module-like library object. You need to use *either* +``ffi.dlopen()`` *or* ``ffi.verify()``, documented below_. + +You can use the library object to call the functions previously declared +by ``ffi.cdef()``, and to read or write global variables. Note that you +can use a single ``cdef()`` to declare functions from multiple +libraries, as long as you load each of them with ``dlopen()`` and access +the functions from the correct one. The ``libpath`` is the file name of the shared library, which can contain a full path or not (in which case it is searched in standard @@ -274,6 +277,8 @@ cannot call functions from a library without linking it in your program, as ``dlopen()`` does dynamically in C. +.. _below: + The verification step --------------------- @@ -281,12 +286,15 @@ ``ffi.verify(source, **kwargs)``: verifies that the current ffi signatures compile on this machine, and return a dynamic library object. The dynamic library can be used to call functions and access global -variables declared by a previous ``ffi.cdef()``. The library is compiled -by the C compiler: it gives you C-level API compatibility (including -calling macros, as long as you declared them as functions in -``ffi.cdef()``). This differs from ``ffi.dlopen()``, which requires -ABI-level compatibility and must be called several times to open several -shared libraries. +variables declared by a previous ``ffi.cdef()``. You don't need to use +``ffi.dlopen()`` in this case. + +The returned library is a custom one, compiled just-in-time by the C +compiler: it gives you C-level API compatibility (including calling +macros, as long as you declared them as functions in ``ffi.cdef()``). +This differs from ``ffi.dlopen()``, which requires ABI-level +compatibility and must be called several times to open several shared +libraries. On top of CPython, the new library is actually a CPython C extension module. This solution constrains you to have a C compiler (future work @@ -322,16 +330,19 @@ if you pass a ``int *`` argument to a function expecting a ``long *``. Moreover, you can use "``...``" in the following places in the ``cdef()`` -for leaving details unspecified (filled in by the C compiler): +for leaving details unspecified, which are then completed by the C +compiler during ``verify()``: * structure declarations: any ``struct`` that ends with "``...;``" is - partial. It will be completed by the compiler. (But note that you - can only access fields that you declared.) Any ``struct`` - declaration without "``...;``" is assumed to be exact, and this is + partial: it may be missing fields and/or have them declared out of order. + This declaration will be corrected by the compiler. (But note that you + can only access fields that you declared, not others.) Any ``struct`` + declaration which doesn't use "``...``" is assumed to be exact, but this is checked: you get a ``VerificationError`` if it is not. * unknown types: the syntax "``typedef ... foo_t;``" declares the type - ``foo_t`` as opaque. + ``foo_t`` as opaque. Useful mainly for when the API takes and returns + ``foo_t *`` without you needing to looking inside the ``foo_t``. * array lengths: when used as structure fields, arrays can have an unspecified length, as in "``int n[];``". The length is completed @@ -356,6 +367,14 @@ to write the ``const`` together with the variable name, as in ``static char *const FOO;``). +Currently, finding automatically the size of an integer type is not +supported. You need to declare them with ``typedef int myint;`` or +``typedef long myint;`` or ``typedef long long myint;`` or their +unsigned equivalent. Depending on the usage, the C compiler might give +warnings if you misdeclare ``myint`` as the wrong type even if it is +equivalent on this platform (e.g. using ``long`` instead of ``long +long`` or vice-versa on 64-bit Linux). + Working with pointers, structures and arrays -------------------------------------------- @@ -393,14 +412,6 @@ ownership, so you must keep it alive. As soon as you forget it, then the casted pointer will point to garbage.) -.. versionchanged:: 0.2 - Allocating a new struct also returns an owning pointer object. - But --- as an exception to the above rule --- dereferencing this - particular pointer object also returns an *owning* struct object. - This is done for cases where you really want to have a struct - object but don't have any convenient place to keep the original - pointer object alive. - 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 @@ -419,10 +430,19 @@ fit nicely in the model, and it does not seem to be needed here). 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 +gives you a fresh cdata object. Unlike the "original" one, these fresh cdata objects don't have ownership: they are merely references to existing memory. +.. versionchanged:: 0.2 + As an exception the above rule, dereferencing a pointer that owns a + *struct* or *union* object returns a cdata struct or union object + that "co-owns" the same memory. Thus in this case there are two + objects that can keep the memory alive. This is done for cases where + you really want to have a struct object but don't have any convenient + place to keep alive the original pointer object (returned by + ``ffi.new()``). + Example:: ffi.cdef("void somefunction(int *);") @@ -487,8 +507,8 @@ array = ffi.new("int[1000]") # CFFI 1st equivalent array = 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)``. Indeed, this is not recommended: +This is useful if the length is not actually a constant, to avoid things +like ``ffi.new("int[%d]" % x)``. Indeed, this is not recommended: ``ffi`` normally caches the string ``"int[]"`` to not need to re-parse it all the time. @@ -501,11 +521,12 @@ same rules as reading a structure field. For example:: ffi.cdef(""" - int foo(int a, int b); + int foo(short a, int b); """) lib = ffi.verify("#include <foo.h>") n = lib.foo(2, 3) # returns a normal integer + lib.foo(40000, 3) # raises OverflowError As an extension, you can pass to ``char *`` arguments a normal Python string (but don't pass a normal Python string to functions that take a @@ -529,7 +550,7 @@ >>> lib.function_returning_a_struct() <cdata 'struct foo_s' owning 8 bytes> -There are a few "obscure-case" limitations to the argument types and +There are a few (obscure) limitations to the argument types and return type. You cannot pass directly as argument a union, nor a struct which uses bitfields (note that passing a *pointer* to anything is fine). If you pass a struct, the struct type cannot have been declared @@ -537,7 +558,8 @@ completely in ``cdef()``. .. versionadded:: 0.2 - Aside from these limitations, functions and callbacks can return structs. + Aside from these limitations, functions and callbacks can now return + structs. Variadic function calls @@ -558,6 +580,7 @@ C.printf("hello, %d\n", ffi.cast("int", 42)) C.printf("hello, %ld\n", ffi.cast("long", 42)) C.printf("hello, %f\n", ffi.cast("double", 42)) + C.printf("hello, %s\n", ffi.new("char[]", "world")) Callbacks @@ -647,7 +670,7 @@ representation of the given C type. If non-empty, the "extra" string is appended (or inserted at the right place in more complicated cases); it can be the name of a variable to declare, or an extra part of the type -like ``"*"`` or ``"[5]"``, so that for example +like ``"*"`` or ``"[5]"``. For example ``ffi.getcname(ffi.typeof(x), "*")`` returns the string representation of the C type "pointer to the same type than x". _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit