[pypy-commit] cffi default: Work in progress on porting to Windows.
arigo
noreply at buildbot.pypy.org
Sat Jun 16 09:42:43 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r384:be6a98ca2f63
Date: 2012-06-16 09:42 +0200
http://bitbucket.org/cffi/cffi/changeset/be6a98ca2f63/
Log: Work in progress on porting to Windows.
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -2,13 +2,16 @@
#include <Python.h>
#include "structmember.h"
+#ifdef MS_WIN32
+#include <windows.h>
+#else
#include <stddef.h>
#include <stdint.h>
#include <dlfcn.h>
#include <errno.h>
-
#include <ffi.h>
#include <sys/mman.h>
+#endif
#include "malloc_closure.h"
@@ -123,7 +126,18 @@
/* whenever running Python code, the errno is saved in this thread-local
variable */
-static __thread int saved_errno = 0;
+#if defined(__GNUC__) && !defined(MS_WIN32)
+# define CFFI_USE_THREAD_LOCALS
+#endif
+
+#ifdef CFFI_USE_THREAD_LOCALS
+static __thread int cffi_saved_errno = 0;
+static void save_errno(void) { cffi_saved_errno = errno; }
+static void *restore_errno(void) { errno = cffi_saved_errno; return NULL; }
+static void init_errno(void) { }
+#else
+#include "non_gcc_errno.h"
+#endif
/************************************************************/
@@ -395,13 +409,13 @@
write_raw_integer_data(char *target, unsigned PY_LONG_LONG source, int size)
{
if (size == sizeof(unsigned char))
- *((unsigned char*)target) = source;
+ *((unsigned char*)target) = (unsigned char)source;
else if (size == sizeof(unsigned short))
- *((unsigned short*)target) = source;
+ *((unsigned short*)target) = (unsigned short)source;
else if (size == sizeof(unsigned int))
- *((unsigned int*)target) = source;
+ *((unsigned int*)target) = (unsigned int)source;
else if (size == sizeof(unsigned long))
- *((unsigned long*)target) = source;
+ *((unsigned long*)target) = (unsigned long)source;
else if (size == sizeof(unsigned PY_LONG_LONG))
*((unsigned PY_LONG_LONG*)target) = source;
else
@@ -425,7 +439,7 @@
write_raw_float_data(char *target, double source, int size)
{
if (size == sizeof(float))
- *((float*)target) = source;
+ *((float*)target) = (float)source;
else if (size == sizeof(double))
*((double*)target) = source;
else
@@ -1037,7 +1051,8 @@
== (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG)) {
/* this case is to handle enums, but also serves as a slight
performance improvement for some other primitive types */
- long value = read_raw_signed_data(cd->c_data, cd->c_type->ct_size);
+ long value = (long)read_raw_signed_data(cd->c_data,
+ cd->c_type->ct_size);
return PyInt_FromLong(value);
}
if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) {
@@ -1445,10 +1460,10 @@
resultdata = buffer + cif_descr->exchange_offset_arg[0];
- errno = saved_errno;
+ restore_errno();
ffi_call(&cif_descr->cif, (void (*)(void))(cd->c_data),
resultdata, buffer_array);
- saved_errno = errno;
+ save_errno();
if (fresult->ct_flags & CT_VOID) {
res = Py_None;
@@ -1829,16 +1844,27 @@
/************************************************************/
+#ifdef MS_WIN32
+typedef HMODULE dl_handle_t;
+#else
+typedef void *dl_handle_t;
+#endif
+
typedef struct {
PyObject_HEAD
- void *dl_handle;
+ dl_handle_t dl_handle;
char *dl_name;
} DynLibObject;
static void dl_dealloc(DynLibObject *dlobj)
{
+#ifdef MS_WIN32
+ if (dlobj->dl_handle)
+ FreeLibrary(dlobj->dl_handle);
+#else
if (dlobj->dl_handle != RTLD_DEFAULT)
dlclose(dlobj->dl_handle);
+#endif
free(dlobj->dl_name);
PyObject_Del(dlobj);
}
@@ -2843,7 +2869,7 @@
static void invoke_callback(ffi_cif *cif, void *result, void **args,
void *userdata)
{
- saved_errno = errno;
+ save_errno();
PyObject *cb_args = (PyObject *)userdata;
CTypeDescrObject *ct = (CTypeDescrObject *)PyTuple_GET_ITEM(cb_args, 0);
@@ -2879,7 +2905,7 @@
Py_XDECREF(py_args);
Py_XDECREF(py_res);
Py_DECREF(cb_args);
- errno = saved_errno;
+ restore_errno();
return;
error:
@@ -3130,7 +3156,11 @@
static PyObject *b_get_errno(PyObject *self, PyObject *noarg)
{
- return PyInt_FromLong(saved_errno);
+ int err;
+ restore_errno();
+ err = errno;
+ errno = 0;
+ return PyInt_FromLong(err);
}
static PyObject *b_set_errno(PyObject *self, PyObject *args)
@@ -3138,7 +3168,9 @@
int i;
if (!PyArg_ParseTuple(args, "i:set_errno", &i))
return NULL;
- saved_errno = i;
+ errno = i;
+ save_errno();
+ errno = 0;
Py_INCREF(Py_None);
return Py_None;
}
@@ -3368,14 +3400,6 @@
return result;
}
-static void _cffi_restore_errno(void) {
- errno = saved_errno;
-}
-
-static void _cffi_save_errno(void) {
- saved_errno = errno;
-}
-
static PyObject *_cffi_from_c_char(char x) {
return PyString_FromStringAndSize(&x, 1);
}
@@ -3399,8 +3423,8 @@
_cffi_from_c_pointer,
_cffi_to_c_pointer,
_cffi_get_struct_layout,
- _cffi_restore_errno,
- _cffi_save_errno,
+ restore_errno,
+ save_errno,
_cffi_from_c_char,
convert_to_object,
};
@@ -3439,4 +3463,6 @@
v = PyCObject_FromVoidPtr((void *)cffi_exports, NULL);
if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
return;
+
+ init_errno();
}
diff --git a/c/non_gcc_errno.h b/c/non_gcc_errno.h
new file mode 100644
--- /dev/null
+++ b/c/non_gcc_errno.h
@@ -0,0 +1,58 @@
+
+#ifndef MS_WIN32
+# error "only GCC or Win32 are supported so far"
+#endif
+
+struct cffi_errno_s {
+ int saved_errno;
+ int saved_lasterror;
+};
+
+static DWORD cffi_tls_index;
+
+static void init_errno(void)
+{
+ cffi_tls_index = TlsAlloc();
+ if (cffi_tls_index == TLS_OUT_OF_INDEXES)
+ PyErr_SetString(PyExc_WindowsError, "TlsAlloc() failed");
+}
+
+static struct cffi_errno_s *_geterrno_object(void)
+{
+ LPVOID p = TlsGetValue(cffi_tls_index);
+
+ if (p == NULL) {
+ p = PyMem_Malloc(sizeof(struct cffi_errno_s));
+ if (p == NULL)
+ return NULL;
+ memset(p, 0, sizeof(struct cffi_errno_s));
+ TlsSetValue(cffi_tls_index, p);
+ }
+ return (struct cffi_errno_s *)p;
+}
+
+static void save_errno(void)
+{
+ int current_err = errno;
+ int current_lasterr = GetLastError();
+ struct cffi_errno_s *p;
+
+ p = _geterrno_object();
+ if (p != NULL) {
+ p->saved_errno = current_err;
+ p->saved_lasterror = current_lasterr;
+ }
+ /* else: cannot report the error */
+}
+
+static void restore_errno(void)
+{
+ struct cffi_errno_s *p;
+
+ p = _geterrno_object();
+ if (p != NULL) {
+ SetLastError(p->saved_lasterror);
+ errno = p->saved_errno;
+ }
+ /* else: cannot report the error */
+}
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,25 @@
-import sys
+import sys, os
from setuptools import setup, Feature, Extension
+sources = ['c/_ffi_backend.c']
+libraries = ['ffi']
+include_dirs = []
+
+
+if sys.platform == 'win32':
+ COMPILE_LIBFFI = 'libffi_msvc' # from the CPython distribution
+else:
+ COMPILE_LIBFFI = None
+
+if COMPILE_LIBFFI:
+ include_dirs.append(COMPILE_LIBFFI)
+ libraries.remove('ffi')
+ sources.extend(os.path.join(COMPILE_LIBFFI, filename)
+ for filename in os.listdir(COMPILE_LIBFFI)
+ if filename.lower().endswith('.c'))
+
+
setup(
name='ffi',
descripton='experimental ffi after the example of lua ffi',
@@ -13,8 +31,9 @@
standard='__pypy__' not in sys.modules,
ext_modules=[
Extension(name='_ffi_backend',
- sources=['c/_ffi_backend.c'],
- libraries=['ffi']),
+ include_dirs=include_dirs,
+ sources=sources,
+ libraries=libraries),
],
),
},
More information about the pypy-commit
mailing list