summaryrefslogtreecommitdiff
path: root/doc/source/overview.rst
blob: 32970faa924e9885cb35d0456857b87373b0b47f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
=======================================================
Overview
=======================================================

.. contents::
   

The first section presents a simple working
example of using CFFI to call a C function in a compiled shared object
(DLL) from Python. CFFI is
flexible and covers several other use cases presented in the second
section. The third section shows how to export Python functions
to a Python interpreter embedded in a C or C++ application. The last
two sections delve deeper in the CFFI library.

Make sure you have `cffi installed`__.

.. __: installation.html

.. _out-of-line-api-level:
.. _real-example:


Main mode of usage
------------------

The main way to use CFFI is as an interface to some already-compiled
shared object which is provided by other means.  Imagine that you have a
system-installed shared object called ``piapprox.dll`` (Windows) or
``libpiapprox.so`` (Linux and others) or ``libpiapprox.dylib`` (OS X),
exporting a function ``float pi_approx(int n);`` that computes some
approximation of pi given a number of iterations. You want to call
this function from Python. Note this method works equally well with a
static library ``piapprox.lib`` (Windows) or ``libpiapprox.a``.

Create the file ``piapprox_build.py``:

.. code-block:: python

      from cffi import FFI
      ffibuilder = FFI()

      # cdef() expects a single string declaring the C types, functions and
      # globals needed to use the shared object. It must be in valid C syntax.
      ffibuilder.cdef("""
          float pi_approx(int n);
      """)

      # set_source() gives the name of the python extension module to
      # produce, and some C source code as a string.  This C code needs
      # to make the declarated functions, types and globals available,
      # so it is often just the "#include".
      ffibuilder.set_source("_pi_cffi",
      """
      	   #include "pi.h"   // the C header of the library
      """,
      	   libraries=['piapprox'])   # library name, for the linker

      if __name__ == "__main__":
          ffibuilder.compile(verbose=True)

Execute this script.  If everything is OK, it should produce
``_pi_cffi.c``, and then invoke the compiler on it.  The produced
``_pi_cffi.c`` contains a copy of the string given in ``set_source()``,
in this example the ``#include "pi.h"``. Afterwards, it contains glue code
for all the functions, types and globals declared in the ``cdef()`` above.

At runtime, you use the extension module like this:

.. code-block:: python

    from _pi_cffi import ffi, lib
    print(lib.pi_approx(5000))

That's all!  In the rest of this page, we describe some more advanced
examples and other CFFI modes.  In particular, there is a complete
example `if you don't have an already-installed C library to call`_.

For more information about the ``cdef()`` and ``set_source()`` methods
of the ``FFI`` class, see `Preparing and Distributing modules`__.

.. __: cdef.html

When your example works, a common alternative to running the build
script manually is to have it run as part of a ``setup.py``.  Here is
an example using the Setuptools distribution:

.. code-block:: python

    from setuptools import setup

    setup(
        ...
        setup_requires=["cffi>=1.0.0"],
        cffi_modules=["piapprox_build:ffibuilder"], # "filename:global"
        install_requires=["cffi>=1.0.0"],
    )


Other CFFI modes
----------------

CFFI can be used in one of four modes: "ABI" versus "API" level,
each with "in-line" or "out-of-line" preparation (or compilation).

The **ABI mode** accesses libraries at the binary level, whereas the
faster **API mode** accesses them with a C compiler.  We explain the
difference in more details below__.

.. __: `abi-versus-api`_

In the **in-line mode,** everything is set up every time you import
your Python code.  In the **out-of-line mode,** you have a separate
step of preparation (and possibly C compilation) that produces a
module which your main program can then import.


Simple example (ABI level, in-line)
+++++++++++++++++++++++++++++++++++

May look familiar to those who have used ctypes_.

.. code-block:: python

    >>> from cffi import FFI
    >>> ffi = FFI()
    >>> ffi.cdef("""
    ...     int printf(const char *format, ...);   // copy-pasted from the man page
    ... """)                                  
    >>> C = ffi.dlopen(None)                     # loads the entire C namespace
    >>> arg = ffi.new("char[]", b"world")        # equivalent to C code: char arg[] = "world";
    >>> C.printf(b"hi there, %s.\n", arg)        # call printf
    hi there, world.
    17                                           # this is the return value
    >>>

Note that ``char *`` arguments expect a ``bytes`` object.  If you have a
``str`` (or a ``unicode`` on Python 2) you need to encode it explicitly
with ``somestring.encode(myencoding)``.

*Python 3 on Windows:* ``ffi.dlopen(None)`` does not work.  This problem
is messy and not really fixable.  The problem does not occur if you try
to call a function from a specific DLL that exists on your system: then
you use ``ffi.dlopen("path.dll")``.

*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().*

If using a C compiler to install your module is an option, it is highly
recommended to use the API mode instead.  (It is also faster.)


Struct/Array Example (minimal, in-line)
+++++++++++++++++++++++++++++++++++++++

.. code-block:: python

    from cffi import FFI
    ffi = FFI()
    ffi.cdef("""
        typedef struct {
            unsigned char r, g, b;
        } pixel_t;
    """)
    image = ffi.new("pixel_t[]", 800*600)

    f = open('data', 'rb')     # binary mode -- important
    f.readinto(ffi.buffer(image))
    f.close()

    image[100].r = 255
    image[100].g = 192
    image[100].b = 128

    f = open('data', 'wb')
    f.write(ffi.buffer(image))
    f.close()

This can be used as a more flexible replacement of the struct_ and
array_ modules, and replaces ctypes_.  You could also call ``ffi.new("pixel_t[600][800]")``
and get a two-dimensional array.

.. _struct: http://docs.python.org/library/struct.html
.. _array: http://docs.python.org/library/array.html
.. _ctypes: http://docs.python.org/library/ctypes.html

*This example does not call any C compiler.*

This example also admits an out-of-line equivalent.  It is similar to
the first example `Main mode of usage`_ 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)``.


API Mode, calling the C standard library
++++++++++++++++++++++++++++++++++++++++

.. code-block:: python

    # 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()

    ffibuilder.set_source("_example",
       r""" // passed to the real C compiler,
            // contains implementation of things declared in cdef()
            #include <sys/types.h>
            #include <pwd.h>

            // We can also define custom wrappers or other functions
            // here (this is an example only):
            static struct passwd *get_pw_for_root(void) {
                return getpwuid(0);
            }
        """,
        libraries=[])   # or a list of libraries to link with
        # (more arguments like setup.py's Extension class:
        # include_dirs=[..], extra_objects=[..], and so on)

    ffibuilder.cdef("""
        // declarations that are shared between Python and C
        struct passwd {
            char *pw_name;
            ...;     // literally dot-dot-dot
        };
        struct passwd *getpwuid(int uid);     // defined in <pwd.h>
        struct passwd *get_pw_for_root(void); // defined in set_source()
    """)

    if __name__ == "__main__":
        ffibuilder.compile(verbose=True)

You need to run the ``example_build.py`` script once to generate
"source code" into the file ``_example.c`` and compile this to a
regular C extension module.  (CFFI selects either Python or C for the
module to generate based on whether the second argument to
``set_source()`` is ``None`` or not.)

*You need a C compiler for this single step.  It produces a file called
e.g. _example.so or _example.pyd.  If needed, it can be distributed in
precompiled form like any other extension module.*

Then, in your main program, you use:

.. code-block:: python

    from _example import ffi, lib

    p = lib.getpwuid(0)
    assert ffi.string(p.pw_name) == b'root'
    p = lib.get_pw_for_root()
    assert ffi.string(p.pw_name) == b'root'

Note that this works independently of the exact C layout of ``struct
passwd`` (it is "API level", as opposed to "ABI level").  It requires
a C compiler in order to run ``example_build.py``, but it is much more
portable than trying to get the details of the fields of ``struct
passwd`` exactly right.  Similarly, in the ``cdef()`` we declared
``getpwuid()`` as taking an ``int`` argument; on some platforms this
might be slightly incorrect---but it does not matter.

Note also that at runtime, the API mode is faster than the ABI mode.

To integrate it inside a ``setup.py`` distribution with Setuptools:

.. code-block:: python

    from setuptools import setup

    setup(
        ...
        setup_requires=["cffi>=1.0.0"],
        cffi_modules=["example_build.py:ffibuilder"],
        install_requires=["cffi>=1.0.0"],
    )


.. _`if you don't have an already-installed C library to call`:

API Mode, calling C sources instead of a compiled library
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

If you want to call some library that is not precompiled, but for which
you have C sources, then the easiest solution is to make a single
extension module that is compiled from both the C sources of this
library, and the additional CFFI wrappers.  For example, say you start
with the files ``pi.c`` and ``pi.h``:

   .. code-block:: C

      /* filename: pi.c*/
      # include <stdlib.h>
      # include <math.h>
       
      /* Returns a very crude approximation of Pi
         given a int: a number of iteration */
      float pi_approx(int n){
      
        double i,x,y,sum=0;
      
        for(i=0;i<n;i++){
      
          x=rand();
          y=rand();
      
          if (sqrt(x*x+y*y) < sqrt((double)RAND_MAX*RAND_MAX))
            sum++; }
      
        return 4*(float)sum/(float)n; }

   .. code-block:: C

      /* filename: pi.h*/
      float pi_approx(int n);
      
Create a script named ``pi_extension_build.py``, building
the C extension:

   .. code-block:: python

      from cffi import FFI
      ffibuilder = FFI()
      
      ffibuilder.cdef("float pi_approx(int n);")
   
      ffibuilder.set_source("_pi",  # name of the output C extension
      """
          #include "pi.h"
      """,
          sources=['pi.c'],   # includes pi.c as additional sources
          libraries=['m'])    # on Unix, link with the math library
   
      if __name__ == "__main__":
          ffibuilder.compile(verbose=True)

Build the extension:
   
   .. code-block:: shell

      python pi_extension_build.py

Observe, in the working directory, the generated output files:
``_pi.c``, ``_pi.o`` and the compiled C extension (called ``_pi.so`` on
Linux for example).  It can be called from Python:

   .. code-block:: python
   
       from _pi.lib import pi_approx
   
       approx = pi_approx(10)
       assert str(pi_approximation).startswith("3.")
   
       approx = pi_approx(10000)
       assert str(approx).startswith("3.1")  


.. _performance:

Purely for performance (API level, out-of-line)
+++++++++++++++++++++++++++++++++++++++++++++++

A variant of the `section above`__ where the goal is not to call an
existing C library, but to compile and call some C function written
directly in the build script:

.. __: real-example_

.. code-block:: python

    # file "example_build.py"

    from cffi import FFI
    ffibuilder = FFI()

    ffibuilder.cdef("int foo(int *, int *, int);")

    ffibuilder.set_source("_example",
    r"""
        static int foo(int *buffer_in, int *buffer_out, int x)
        {
            /* some algorithm that is seriously faster in C than in Python */
        }
    """)

    if __name__ == "__main__":
        ffibuilder.compile(verbose=True)

.. code-block:: python

    # file "example.py"

    from _example import ffi, lib

    buffer_in = ffi.new("int[]", 1000)
    # initialize buffer_in here...

    # easier to do all buffer allocations in Python and pass them to C,
    # even for output-only arguments
    buffer_out = ffi.new("int[]", 1000)

    result = lib.foo(buffer_in, buffer_out, 1000)

*You need a C compiler to run example_build.py, once.  It produces a
file called e.g. _example.so or _example.pyd.  If needed, it can be
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()
    # Note that the actual source is None
    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"],
    )

In summary, this mode is useful when you wish to declare many C structures but
do not need fast interaction with a shared object. It is useful for parsing
binary files, for instance.


In-line, API level
++++++++++++++++++

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 and avoids a number of problems when the project grows in
size.


.. _embedding:

Embedding
---------

*New in version 1.5.*

CFFI can be used for embedding__: creating a standard
dynamically-linked library (``.dll`` under Windows, ``.so`` elsewhere)
which can be used from a C application.

.. code-block:: python

    import cffi
    ffibuilder = cffi.FFI()

    ffibuilder.embedding_api("""
        int do_stuff(int, int);
    """)

    ffibuilder.set_source("my_plugin", "")

    ffibuilder.embedding_init_code("""
        from my_plugin import ffi

        @ffi.def_extern()
        def do_stuff(x, y):
            print("adding %d and %d" % (x, y))
            return x + y
    """)

    ffibuilder.compile(target="plugin-1.5.*", verbose=True)

This simple example creates ``plugin-1.5.dll`` or ``plugin-1.5.so`` as
a DLL with a single exported function, ``do_stuff()``.  You execute
the script above once, with the interpreter you want to have
internally used; it can be CPython 2.x or 3.x or PyPy.  This DLL can
then be used "as usual" from an application; the application doesn't
need to know that it is talking with a library made with Python and
CFFI.  At runtime, when the application calls ``int do_stuff(int,
int)``, the Python interpreter is automatically initialized and ``def
do_stuff(x, y):`` gets called.  `See the details in the documentation
about embedding.`__

.. __: embedding.html
.. __: embedding.html


What actually happened?
-----------------------

The CFFI interface operates on the same level as C - you declare types
and functions using the same syntax as you would define them in C.  This
means that most of the documentation or examples can be copied straight
from the man pages.

The declarations can contain **types, functions, constants**
and **global variables.** What you pass to the ``cdef()`` must not
contain more than that; in particular, ``#ifdef`` or ``#include``
directives are not supported.  The cdef in the above examples are just
that - they declared "there is a function in the C level with this
given signature", or "there is a struct type with this shape".

In the ABI examples, the ``dlopen()`` calls load libraries manually.
At the binary level, a program is split into multiple namespaces---a
global one (on some platforms), plus one namespace per library.  So
``dlopen()`` returns a ``<FFILibrary>`` object, and this object has
got as attributes all function, constant and variable symbols that are
coming from this library and that have been declared in the
``cdef()``.  If you have several interdependent libraries to load,
you would call ``cdef()`` only once but ``dlopen()`` several times.

By opposition, the API mode works more closely like a C program: the C
linker (static or dynamic) is responsible for finding any symbol used.
You name the libraries in the ``libraries`` keyword argument to
``set_source()``, but never need to say which symbol comes
from which library.
Other common arguments to ``set_source()`` include ``library_dirs`` and
``include_dirs``; all these arguments are passed to the standard
distutils/setuptools.

The ``ffi.new()`` lines allocate C objects.  They are filled
with zeroes initially, unless the optional second argument is used.
If specified, this argument gives an "initializer", like you can use
with C code to initialize global variables.

The actual ``lib.*()`` function calls should be obvious: it's like C.


.. _abi-versus-api:

ABI versus API
--------------

Accessing the C library at the binary level ("ABI") is fraught
with problems, particularly on non-Windows platforms.

The most immediate drawback of the ABI level is that calling functions
needs to go through the very general *libffi* library, which is slow
(and not always perfectly tested on non-standard platforms).  The API
mode instead compiles a CPython C wrapper that directly invokes the
target function.  It can be massively faster (and works
better than libffi ever will).

The more fundamental reason to prefer the API mode is that *the C
libraries are typically meant to be used with a C compiler.* You are not
supposed to do things like guess where fields are in the structures.
The "real example" above shows how CFFI uses a C compiler under the
hood: this example uses ``set_source(..., "C source...")`` and never
``dlopen()``.  When using this approach,
we have the advantage that we can use literally "``...``" at various places in
the ``cdef()``, and the missing information will be completed with the
help of the C compiler.  CFFI will turn this into a single C source file,
which contains the "C source" part unmodified, followed by some
"magic" C code and declarations derived from the ``cdef()``.  When
this C file is compiled, the resulting C extension module will contain
all the information we need---or the C compiler will give warnings or
errors, as usual e.g. if we misdeclare some function's signature.

Note that the "C source" part from ``set_source()`` can contain
arbitrary C code.  You can use this to declare some
more helper functions written in C.  To export
these helpers to Python, put their signature in the ``cdef()`` too.
(You can use the ``static`` C keyword in the "C source" part,
as in ``static int myhelper(int x) { return x * 42; }``,
because these helpers are only
referenced from the "magic" C code that is generated afterwards in the
same C file.)

This can be used for example to wrap "crazy" macros into more standard
C functions.  The extra layer of C can be useful for other reasons
too, like calling functions that expect some complicated argument
structures that you prefer to build in C rather than in Python.  (On
the other hand, if all you need is to call "function-like" macros,
then you can directly declare them in the ``cdef()`` as if they were
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 (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.

.. __: real-example_