Author: Armin Rigo <ar...@tunes.org> Branch: extradoc Changeset: r5576:4e6f2b0b4afb Date: 2016-01-02 19:22 +0100 http://bitbucket.org/pypy/extradoc/changeset/4e6f2b0b4afb/
Log: Draft blog post diff --git a/blog/draft/cffi-embedding.rst b/blog/draft/cffi-embedding.rst new file mode 100644 --- /dev/null +++ b/blog/draft/cffi-embedding.rst @@ -0,0 +1,81 @@ +======================== +Using CFFI for embedding +======================== + +CFFI_ has been a great success so far to call C libraries in your +Python programs, in a way that is both simple and that works across +CPython 2.x and 3.x and PyPy. + +We are now adding support for *embedding* Python inside non-Python +programs. This is traditionally done using the CPython C API: from C +code, you call ``Py_Initialize()`` and then some other functions like +``PyRun_SimpleString()``. In the simple cases it is, indeed, simple +enough; but it can become a more complicated story if you throw in +supporting application-dependent object types, and correctly running +on multiple threads, and so on. + +Moreover, this approach is specific to CPython (2.x or 3.x, which you +can do in a similar way). It does not work on PyPy, which has its own +smaller `embedding API`_. + +CFFI now supports embedding directly---and there is no fixed API at +all. The idea is to write some Python script with a ``cdef()`` which +declares a number of ``extern "Python"`` functions. When running the +script, it creates the C source code and compile it to a +dynamically-linked library (``.so`` on Linux). This is the same as in +the regular API-mode usage, and ``extern "Python"`` was `introduced in +CFFI 1.4`_. What is new is that you also give a bit of +initialization-time Python code directly in the script, which will be +compiled into the ``.so`` too---and the ``extern "Python"`` are now +also "exported" from the dynamically-linked library as regular C +functions. + +In other words, this library can now be used directly from any C +program (and it is still importable in Python). It exposes the C API +of your choice, which you specified with the ``extern "Python"`` +declarations. You can use it to make whatever custom API makes sense +in your particular case. You can even make directly a "plug-in" for +any program that supports them, just by exporting the API expected for +such plugins. + +This is still being finalized, but please try it out. (You can also +see `embedding.py`_ directly online here for a quick glance.) + +* get the branch ``static-callback-embedding`` of CFFI (``hg clone https://bitbucket.org/cffi/cffi && hg up static-callback-embedding``) + +* make the ``_cffi_backend.so`` (``python setup_base.py build_ext -f -i``) + +* run ``embedding`` in the ``demo`` directory (``cd demo; PYTHONPATH=.. python embedding.py``) + +* run ``gcc`` to build the C sources (``gcc -shared -fPIC _embedding_cffi.c -o _embedding_cffi.so -lpython2.7 -I/usr/include/python2.7``) + +* try out the demo C program in ``embedding_test.c`` (``gcc embedding_test.c _embedding_cffi.so && PYTHONPATH=.. LD_LIBRARY_PATH=. a.out``). + +Note that if you get ``ImportError: cffi extension module +'_embedding_cffi' has unknown version 0x2701``, it means that the +``_cffi_backend`` module loaded is a pre-installed one instead of the +more recent one in ``..``. Be sure to use ``PYTHONPATH`` for now. + +Very similar steps can be followed on PyPy, but it requires the +``cffi-static-callback-embedding`` branch of PyPy, which you must +first translate from sources. + +You get a CPython/PyPy that is automatically initialized (using locks +in case of multi-threading) the first time any of the ``extern +"Python"`` functions is called from the C program. The custom +initialization-time Python code is run at that time too. If this code +starts to be big, you may consider moving it to several modules or +packages and importing them from the initialization-time Python code; +in that case you have to be careful about setting up the correct +``sys.path``. + +Note that right now it does not support CPython's notion of multiple +subinterpreters. The logic creates a single global Python interpreter, +and everything is run in that context. Idea about how to support that +cleanly would be welcome ``:-)`` More generally, any feedback is +appreciated. + + +Have fun, + +Armin _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit