mirror of
https://github.com/python/cpython.git
synced 2025-07-30 22:54:16 +00:00
Revert revisions 63943 and 63942 (Issue #1798: Add ctypes calling
convention that allows safe access to errno) This code does not yet work on OS X (__thread storage specifier not available), so i needs a configure check plus a more portable solution.
This commit is contained in:
parent
8f22b88e28
commit
d5bb9215c9
7 changed files with 27 additions and 312 deletions
|
@ -3271,7 +3271,7 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
thunk = AllocFunctionCallback(callable,
|
||||
dict->argtypes,
|
||||
dict->restype,
|
||||
dict->flags);
|
||||
dict->flags & FUNCFLAG_CDECL);
|
||||
if (!thunk)
|
||||
return NULL;
|
||||
|
||||
|
@ -5273,17 +5273,6 @@ init_ctypes(void)
|
|||
if (!m)
|
||||
return;
|
||||
|
||||
#ifdef MS_WIN32
|
||||
dwTlsIndex_LastError = TlsAlloc();
|
||||
dwTlsIndex_errno = TlsAlloc();
|
||||
if (dwTlsIndex_LastError == TLS_OUT_OF_INDEXES
|
||||
|| dwTlsIndex_errno == TLS_OUT_OF_INDEXES) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Could not allocate TLSIndex for LastError value");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_pointer_type_cache = PyDict_New();
|
||||
if (_pointer_type_cache == NULL)
|
||||
return;
|
||||
|
@ -5405,8 +5394,6 @@ init_ctypes(void)
|
|||
PyModule_AddObject(m, "FUNCFLAG_STDCALL", PyInt_FromLong(FUNCFLAG_STDCALL));
|
||||
#endif
|
||||
PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL));
|
||||
PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyInt_FromLong(FUNCFLAG_USE_ERRNO));
|
||||
PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyInt_FromLong(FUNCFLAG_USE_LASTERROR));
|
||||
PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI));
|
||||
PyModule_AddStringConstant(m, "__version__", "1.1.0");
|
||||
|
||||
|
|
|
@ -189,7 +189,6 @@ static void _CallPythonObject(void *mem,
|
|||
SETFUNC setfunc,
|
||||
PyObject *callable,
|
||||
PyObject *converters,
|
||||
int flags,
|
||||
void **pArgs)
|
||||
{
|
||||
Py_ssize_t i;
|
||||
|
@ -272,22 +271,8 @@ static void _CallPythonObject(void *mem,
|
|||
#define CHECK(what, x) \
|
||||
if (x == NULL) _AddTraceback(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print()
|
||||
|
||||
if (flags & FUNCFLAG_USE_ERRNO)
|
||||
_swap_errno();
|
||||
#ifdef MS_WIN32
|
||||
if (flags & FUNCFLAG_USE_LASTERROR)
|
||||
_swap_last_error();
|
||||
#endif
|
||||
|
||||
result = PyObject_CallObject(callable, arglist);
|
||||
CHECK("'calling callback function'", result);
|
||||
|
||||
#ifdef MS_WIN32
|
||||
if (flags & FUNCFLAG_USE_LASTERROR)
|
||||
_swap_last_error();
|
||||
#endif
|
||||
if (flags & FUNCFLAG_USE_ERRNO)
|
||||
_swap_errno();
|
||||
if ((restype != &ffi_type_void) && result) {
|
||||
PyObject *keep;
|
||||
assert(setfunc);
|
||||
|
@ -337,7 +322,6 @@ static void closure_fcn(ffi_cif *cif,
|
|||
p->setfunc,
|
||||
p->callable,
|
||||
p->converters,
|
||||
p->flags,
|
||||
args);
|
||||
}
|
||||
|
||||
|
@ -367,7 +351,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
|
|||
CThunkObject *AllocFunctionCallback(PyObject *callable,
|
||||
PyObject *converters,
|
||||
PyObject *restype,
|
||||
int flags)
|
||||
int is_cdecl)
|
||||
{
|
||||
int result;
|
||||
CThunkObject *p;
|
||||
|
@ -387,7 +371,6 @@ CThunkObject *AllocFunctionCallback(PyObject *callable,
|
|||
goto error;
|
||||
}
|
||||
|
||||
p->flags = flags;
|
||||
for (i = 0; i < nArgs; ++i) {
|
||||
PyObject *cnv = PySequence_GetItem(converters, i);
|
||||
if (cnv == NULL)
|
||||
|
@ -415,7 +398,7 @@ CThunkObject *AllocFunctionCallback(PyObject *callable,
|
|||
|
||||
cc = FFI_DEFAULT_ABI;
|
||||
#if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64)
|
||||
if ((flags & FUNCFLAG_CDECL) == 0)
|
||||
if (is_cdecl == 0)
|
||||
cc = FFI_STDCALL;
|
||||
#endif
|
||||
result = ffi_prep_cif(&p->cif, cc,
|
||||
|
|
|
@ -83,133 +83,6 @@
|
|||
#define DONT_USE_SEH
|
||||
#endif
|
||||
|
||||
/*
|
||||
ctypes maintains a module-global, but thread-local, variable that contains
|
||||
an error number; called 'ctypes_errno' for this discussion. This variable
|
||||
is a private copy of the systems 'errno' value; the copy is swapped with the
|
||||
'errno' variable on several occasions.
|
||||
|
||||
Foreign functions created with CDLL(..., use_errno=True), when called, swap
|
||||
the values just before the actual function call, and swapped again
|
||||
immediately afterwards. The 'use_errno' parameter defaults to False, in
|
||||
this case 'ctypes_errno' is not touched.
|
||||
|
||||
The values are also swapped immeditately before and after ctypes callback
|
||||
functions are called, if the callbacks are constructed using the new
|
||||
optional use_errno parameter set to True: CFUNCTYPE(..., use_errno=TRUE) or
|
||||
WINFUNCTYPE(..., use_errno=True).
|
||||
|
||||
Two new ctypes functions are provided to access the 'ctypes_errno' value
|
||||
from Python:
|
||||
|
||||
- ctypes.set_errno(value) sets ctypes_errno to 'value', the previous
|
||||
ctypes_errno value is returned.
|
||||
|
||||
- ctypes.get_errno() returns the current ctypes_errno value.
|
||||
|
||||
---
|
||||
|
||||
On Windows, the same scheme is implemented for the error value which is
|
||||
managed by the GetLastError() and SetLastError() windows api calls.
|
||||
|
||||
The ctypes functions are 'ctypes.set_last_error(value)' and
|
||||
'ctypes.get_last_error()', the CDLL and WinDLL optional parameter is named
|
||||
'use_last_error', defaults to False.
|
||||
|
||||
---
|
||||
|
||||
On Windows, TlsSetValue and TlsGetValue calls are used to provide thread
|
||||
local storage for the variables; ctypes compiled with __GNUC__ uses __thread
|
||||
variables.
|
||||
*/
|
||||
|
||||
#if defined(MS_WIN32)
|
||||
DWORD dwTlsIndex_LastError;
|
||||
DWORD dwTlsIndex_errno;
|
||||
|
||||
void
|
||||
_swap_last_error(void)
|
||||
{
|
||||
DWORD temp = GetLastError();
|
||||
SetLastError((DWORD)TlsGetValue(dwTlsIndex_LastError));
|
||||
TlsSetValue(dwTlsIndex_LastError, (void *)temp);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_last_error(PyObject *self, PyObject *args)
|
||||
{
|
||||
return PyInt_FromLong((DWORD)TlsGetValue(dwTlsIndex_LastError));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_last_error(PyObject *self, PyObject *args)
|
||||
{
|
||||
DWORD new_value, prev_value;
|
||||
if (!PyArg_ParseTuple(args, "i", &new_value))
|
||||
return NULL;
|
||||
prev_value = (DWORD)TlsGetValue(dwTlsIndex_LastError);
|
||||
TlsSetValue(dwTlsIndex_LastError, (void *)new_value);
|
||||
return PyInt_FromLong(prev_value);
|
||||
}
|
||||
|
||||
void
|
||||
_swap_errno(void)
|
||||
{
|
||||
int temp = errno;
|
||||
errno = (int)TlsGetValue(dwTlsIndex_errno);
|
||||
TlsSetValue(dwTlsIndex_errno, (void *)temp);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_errno(PyObject *self, PyObject *args)
|
||||
{
|
||||
return PyInt_FromLong((int)TlsGetValue(dwTlsIndex_errno));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_errno(PyObject *self, PyObject *args)
|
||||
{
|
||||
int new_value, prev_value;
|
||||
if (!PyArg_ParseTuple(args, "i", &new_value))
|
||||
return NULL;
|
||||
prev_value = (int)TlsGetValue(dwTlsIndex_errno);
|
||||
TlsSetValue(dwTlsIndex_errno, (void *)new_value);
|
||||
return PyInt_FromLong(prev_value);
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
static __thread int ctypes_errno;
|
||||
|
||||
void
|
||||
_swap_errno(void)
|
||||
{
|
||||
int temp = errno;
|
||||
errno = ctypes_errno;
|
||||
ctypes_errno = temp;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_errno(PyObject *self, PyObject *args)
|
||||
{
|
||||
return PyInt_FromLong(ctypes_errno);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_errno(PyObject *self, PyObject *args)
|
||||
{
|
||||
int new_errno, prev_errno;
|
||||
if (!PyArg_ParseTuple(args, "i", &new_errno))
|
||||
return NULL;
|
||||
prev_errno = ctypes_errno;
|
||||
ctypes_errno = new_errno;
|
||||
return PyInt_FromLong(prev_errno);
|
||||
}
|
||||
#else
|
||||
|
||||
#error "TLS not implemented in this configuration"
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MS_WIN32
|
||||
PyObject *ComError;
|
||||
|
||||
|
@ -787,11 +660,7 @@ static int _call_function_pointer(int flags,
|
|||
if ((flags & FUNCFLAG_PYTHONAPI) == 0)
|
||||
Py_UNBLOCK_THREADS
|
||||
#endif
|
||||
if (flags & FUNCFLAG_USE_ERRNO)
|
||||
_swap_errno();
|
||||
#ifdef MS_WIN32
|
||||
if (flags & FUNCFLAG_USE_LASTERROR)
|
||||
_swap_last_error();
|
||||
#ifndef DONT_USE_SEH
|
||||
__try {
|
||||
#endif
|
||||
|
@ -806,11 +675,7 @@ static int _call_function_pointer(int flags,
|
|||
;
|
||||
}
|
||||
#endif
|
||||
if (flags & FUNCFLAG_USE_LASTERROR)
|
||||
_swap_last_error();
|
||||
#endif
|
||||
if (flags & FUNCFLAG_USE_ERRNO)
|
||||
_swap_errno();
|
||||
#ifdef WITH_THREAD
|
||||
if ((flags & FUNCFLAG_PYTHONAPI) == 0)
|
||||
Py_BLOCK_THREADS
|
||||
|
@ -1802,8 +1667,6 @@ pointer(PyObject *self, PyObject *arg)
|
|||
}
|
||||
|
||||
PyMethodDef module_methods[] = {
|
||||
{"get_errno", get_errno, METH_NOARGS},
|
||||
{"set_errno", set_errno, METH_VARARGS},
|
||||
{"POINTER", POINTER, METH_O },
|
||||
{"pointer", pointer, METH_O },
|
||||
{"_unpickle", unpickle, METH_VARARGS },
|
||||
|
@ -1812,8 +1675,6 @@ PyMethodDef module_methods[] = {
|
|||
{"set_conversion_mode", set_conversion_mode, METH_VARARGS, set_conversion_mode_doc},
|
||||
#endif
|
||||
#ifdef MS_WIN32
|
||||
{"get_last_error", get_last_error, METH_NOARGS},
|
||||
{"set_last_error", set_last_error, METH_VARARGS},
|
||||
{"CopyComPointer", copy_com_pointer, METH_VARARGS, copy_com_pointer_doc},
|
||||
{"FormatError", format_error, METH_VARARGS, format_error_doc},
|
||||
{"LoadLibrary", load_library, METH_VARARGS, load_library_doc},
|
||||
|
|
|
@ -87,7 +87,6 @@ typedef struct {
|
|||
PyObject_VAR_HEAD
|
||||
ffi_closure *pcl; /* the C callable */
|
||||
ffi_cif cif;
|
||||
int flags;
|
||||
PyObject *converters;
|
||||
PyObject *callable;
|
||||
PyObject *restype;
|
||||
|
@ -186,7 +185,7 @@ extern PyMethodDef module_methods[];
|
|||
extern CThunkObject *AllocFunctionCallback(PyObject *callable,
|
||||
PyObject *converters,
|
||||
PyObject *restype,
|
||||
int flags);
|
||||
int stdcall);
|
||||
/* a table entry describing a predefined ctypes type */
|
||||
struct fielddesc {
|
||||
char code;
|
||||
|
@ -304,8 +303,6 @@ PyObject *_CallProc(PPROC pProc,
|
|||
#define FUNCFLAG_CDECL 0x1
|
||||
#define FUNCFLAG_HRESULT 0x2
|
||||
#define FUNCFLAG_PYTHONAPI 0x4
|
||||
#define FUNCFLAG_USE_ERRNO 0x8
|
||||
#define FUNCFLAG_USE_LASTERROR 0x10
|
||||
|
||||
#define TYPEFLAG_ISPOINTER 0x100
|
||||
#define TYPEFLAG_HASPOINTER 0x200
|
||||
|
@ -424,16 +421,8 @@ extern int IsSimpleSubType(PyObject *obj);
|
|||
|
||||
extern PyObject *_pointer_type_cache;
|
||||
|
||||
extern void _swap_errno(void);
|
||||
|
||||
#ifdef MS_WIN32
|
||||
|
||||
extern void _swap_last_error(void);
|
||||
|
||||
extern PyObject *ComError;
|
||||
|
||||
extern DWORD dwTlsIndex_LastError;
|
||||
extern DWORD dwTlsIndex_errno;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue