[pypy-commit] pypy default: Embedding documentation updated
vlukas
noreply at buildbot.pypy.org
Tue Apr 1 09:26:28 CEST 2014
Author: Lukas Vacek <lucas.vacek at gmail.com>
Branch:
Changeset: r70369:fefe963624fe
Date: 2014-03-26 01:04 +0000
http://bitbucket.org/pypy/pypy/changeset/fefe963624fe/
Log: Embedding documentation updated
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -1,3 +1,4 @@
+
Embedding PyPy
--------------
@@ -50,7 +51,7 @@
.. function:: int pypy_execute_source_ptr(char* source, void* ptr);
- .. note:: Not available in <=2.2.1 yet
+ .. note:: Not available in PyPy <= 2.2.1
Just like the above, except it registers a magic argument in the source
scope as ``c_argument``, where ``void*`` is encoded as Python int.
@@ -75,7 +76,6 @@
.. code-block:: c
- #include "include/PyPy.h"
#include <stdio.h>
const char source[] = "print 'hello from pypy'";
@@ -101,9 +101,26 @@
Worked!
+Missing PyPy.h
+--------------
+
+.. note:: PyPy.h is in the nigthly builds and goes to new PyPy releases (>2.2.1).
+
+For PyPy <= 2.2.1, you can download PyPy.h from PyPy repository (it has been added in commit c4cd6ec):
+
+.. code-block:: bash
+
+ cd /opt/pypy/include
+ wget https://bitbucket.org/pypy/pypy/raw/c4cd6eca9358066571500ac82aaacfdaa3889e8c/include/PyPy.h
+
+
More advanced example
---------------------
+.. note:: This example depends on pypy_execute_source_ptr which is not available
+ in PyPy <= 2.2.1. You might want to see the alternative example
+ below.
+
Typically we need something more to do than simply execute source. The following
is a fully fledged example, please consult cffi documentation for details.
It's a bit longish, but it captures a gist what can be done with the PyPy
@@ -162,6 +179,95 @@
is that we would pass a struct full of callbacks to ``pypy_execute_source_ptr``
and fill the structure from Python side for the future use.
+Alternative example
+-------------------
+
+As ``pypy_execute_source_ptr`` is not available in PyPy 2.2.1, you might want to try
+an alternative approach which relies on -export-dynamic flag to the GNU linker.
+The downside to this approach is that it is platform dependent.
+
+.. code-block:: c
+
+ #include "include/PyPy.h"
+ #include <stdio.h>
+
+ char source[] = "from cffi import FFI\n\
+ ffi = FFI()\n\
+ @ffi.callback('int(int)')\n\
+ def func(a):\n\
+ print 'Got from C %d' % a\n\
+ return a * 2\n\
+ ffi.cdef('int callback(int (*func)(int));')\n\
+ lib = ffi.verify('int callback(int (*func)(int));')\n\
+ lib.callback(func)\n\
+ print 'finished the Python part'\n\
+ ";
+
+ int callback(int (*func)(int))
+ {
+ printf("Calling to Python, result: %d\n", func(3));
+ }
+
+ int main()
+ {
+ int res;
+ void *lib, *func;
+
+ rpython_startup_code();
+ res = pypy_setup_home("/home/lukas/dev/pypy-2.2.1-src/libpypy-c.so", 1);
+ if (res) {
+ printf("Error setting pypy home!\n");
+ return 1;
+ }
+ res = pypy_execute_source(source);
+ if (res) {
+ printf("Error calling pypy_execute_source!\n");
+ }
+ return res;
+ }
+
+
+Make sure to pass -export-dynamic flag when compiling::
+
+ $ gcc -g -o x x.c -lpypy-c -L. -export-dynamic
+ $ LD_LIBRARY_PATH=. ./x
+ Got from C 3
+ Calling to Python, result: 6
+ finished the Python part
+
+Finding pypy_home
+-----------------
+
+Function pypy_setup_home takes one parameter - the path to libpypy. There's currently no "clean" way (pkg-config comes to mind) how to find this path. You can try the following (GNU-specific) hack (don't forget to link against *dl*):
+
+.. code-block:: c
+
+ #if !(_GNU_SOURCE)
+ #define _GNU_SOURCE
+ #endif
+
+ #include <dlfcn.h>
+ #include <limits.h>
+ #include <stdlib.h>
+
+ // caller should free returned pointer to avoid memleaks
+ // returns NULL on error
+ char* guess_pypyhome() {
+ // glibc-only (dladdr is why we #define _GNU_SOURCE)
+ Dl_info info;
+ void *_rpython_startup_code = dlsym(0,"rpython_startup_code");
+ if (_rpython_startup_code == 0) {
+ return 0;
+ }
+ if (dladdr(_rpython_startup_code, &info) != 0) {
+ const char* lib_path = info.dli_fname;
+ char* lib_realpath = realpath(lib_path, 0);
+ return lib_realpath;
+ }
+ return 0;
+ }
+
+
Threading
---------
More information about the pypy-commit
mailing list