summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-12-05 17:28:22 +0100
committerArmin Rigo <arigo@tunes.org>2015-12-05 17:28:22 +0100
commit1b7657ee41e926fdfb0eae2e8fcc2e9434f751d4 (patch)
treedb92704ce95c49f66e2e4c08218d656bdd6e0dee
parent5e6dd24e3bb3a267472e1880bd8d7f0b64c44ab0 (diff)
downloadcffi-1b7657ee41e926fdfb0eae2e8fcc2e9434f751d4.tar.gz
in-progress
-rw-r--r--c/call_python.c4
-rw-r--r--cffi/_embedding.h54
-rw-r--r--cffi/recompiler.py1
-rw-r--r--demo/embedding.py2
4 files changed, 47 insertions, 14 deletions
diff --git a/c/call_python.c b/c/call_python.c
index 8196000..1943e7d 100644
--- a/c/call_python.c
+++ b/c/call_python.c
@@ -146,9 +146,9 @@ static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
return 2; /* out of memory? */
}
-#if (defined(WITH_THREAD) && !defined(!_MSC_VER) && \
+#if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
!defined(__amd64__) && !defined(__x86_64__) && \
- !defined(__i386__) && !defined(__i386)
+ !defined(__i386__) && !defined(__i386))
# define read_barrier() __sync_synchronize()
#else
# define read_barrier() (void)0
diff --git a/cffi/_embedding.h b/cffi/_embedding.h
index acb4024..c6acd70 100644
--- a/cffi/_embedding.h
+++ b/cffi/_embedding.h
@@ -110,6 +110,8 @@ static int _cffi_initialize_python(void)
/* This initializes Python, imports _cffi_backend, and then the
present .dll/.so is set up as a CPython C extension module.
*/
+ int result;
+ PyObject *pycode=NULL, *m=NULL, *global_dict, *x;
PyEval_AcquireLock(); /* acquire the GIL */
@@ -136,8 +138,19 @@ static int _cffi_initialize_python(void)
/* Now run the Python code provided to ffi.embedding_init_code().
*/
- if (PyRun_SimpleString(_CFFI_PYTHON_STARTUP_CODE) < 0)
+ m = PyImport_ImportModule(_CFFI_MODULE_NAME);
+ if (m == NULL)
goto error;
+ pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE,
+ "<init code for '" _CFFI_MODULE_NAME "'>",
+ Py_file_input);
+ if (pycode == NULL)
+ goto error;
+ global_dict = PyModule_GetDict(m);
+ x = PyEval_EvalCode((PyCodeObject *)pycode, global_dict, global_dict);
+ if (x == NULL)
+ goto error;
+ Py_DECREF(x);
/* Done! Now if we've been called from
_cffi_start_and_call_python() in an ``extern "Python"``, we can
@@ -147,9 +160,12 @@ static int _cffi_initialize_python(void)
_cffi_backend module) will find that the reference is still
missing and print an error.
*/
-
+ result = 0;
+ done:
+ Py_XDECREF(pycode);
+ Py_XDECREF(m);
PyEval_ReleaseLock(); /* release the GIL */
- return 0;
+ return result;
error:;
{
@@ -184,16 +200,17 @@ static int _cffi_initialize_python(void)
PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0);
PyFile_WriteString("\n\n", f);
}
- PyEval_ReleaseLock(); /* release the GIL */
- return -1;
}
+ result = -1;
+ goto done;
}
static void _cffi_carefully_make_gil(void)
{
-#ifdef WITH_THREAD
/* This initializes the GIL. It can be called completely
- concurrently from unrelated threads.
+ concurrently from unrelated threads. It assumes that we don't
+ hold the GIL before (if it exists), and we don't hold it
+ afterwards.
PyEval_InitThreads() must not be called concurrently at all.
So we use a global variable as a simple spin lock. This global
@@ -204,6 +221,7 @@ static void _cffi_carefully_make_gil(void)
never-used word for this lock. (Yes, I know it's really
obscure.)
*/
+#ifdef WITH_THREAD
void *volatile *lock = (void *volatile *)&PyEllipsis_Type.tp_dealloc;
while (1) { /* spin loop */
@@ -244,12 +262,25 @@ static void _cffi_carefully_make_gil(void)
PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */
-extern int pypy_init_embedded_cffi_module(void(const void *[]));
+static struct _cffi_pypy_init_s {
+ const char *name;
+ void (*func)(const void *[]);
+ const char *code;
+} _cffi_pypy_init = {
+ _CFFI_MODULE_NAME,
+ _CFFI_PYTHON_STARTUP_FUNC,
+ _CFFI_PYTHON_STARTUP_CODE,
+};
+
+extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *);
+
+static void _cffi_carefully_make_gil(void)
+{
+}
static int _cffi_initialize_python(void)
{
- return pypy_init_embedded_cffi_module(0xB011, _CFFI_PYTHON_STARTUP_FUNC,
- _CFFI_PYTHON_STARTUP_CODE);
+ return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init);
}
/********** end PyPy-specific section **********/
@@ -302,6 +333,9 @@ static _cffi_call_python_fnptr _cffi_start_python(void)
/* Here the GIL exists, but we don't have it. We're only protected
from concurrency by the reentrant mutex. */
+
+ /* This file ignores subinterpreters and can only initialize the
+ embedded module once, in the main interpreter. */
if (!called) {
called = 1; /* invoke _cffi_initialize_python() only once,
but don't set '_cffi_call_python' right now,
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
index fe98cb5..c717e74 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -285,6 +285,7 @@ class Recompiler:
# and include an extra file
base_module_name = self.module_name.split('.')[-1]
if self.ffi._embedding_init_code is not None:
+ prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,))
prnt('#define _CFFI_PYTHON_STARTUP_CODE %s' %
(self._string_literal(self.ffi._embedding_init_code),))
prnt('#ifdef PYPY_VERSION')
diff --git a/demo/embedding.py b/demo/embedding.py
index 0d776ef..365238d 100644
--- a/demo/embedding.py
+++ b/demo/embedding.py
@@ -7,8 +7,6 @@ ffi.cdef("""
""", dllexport=True)
ffi.embedding_init_code("""
- from _embedding_cffi import ffi, lib
-
print "preparing"
@ffi.def_extern()