summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/ctypes/__init__.py72
-rw-r--r--Lib/ctypes/test/test_errno.py76
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_ctypes/_ctypes.c15
-rw-r--r--Modules/_ctypes/callbacks.c21
-rw-r--r--Modules/_ctypes/callproc.c139
-rw-r--r--Modules/_ctypes/ctypes.h13
7 files changed, 27 insertions, 312 deletions
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index d3e11dc..41d39dc 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -33,9 +33,7 @@ if _os.name == "posix" and _sys.platform == "darwin":
DEFAULT_MODE = RTLD_GLOBAL
from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
- FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI, \
- FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \
- FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR
+ FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI
"""
WINOLEAPI -> HRESULT
@@ -75,9 +73,8 @@ def c_buffer(init, size=None):
return create_string_buffer(init, size)
_c_functype_cache = {}
-def CFUNCTYPE(restype, *argtypes, **kw):
- """CFUNCTYPE(restype, *argtypes,
- use_errno=False, use_last_error=False) -> function prototype.
+def CFUNCTYPE(restype, *argtypes):
+ """CFUNCTYPE(restype, *argtypes) -> function prototype.
restype: the result type
argtypes: a sequence specifying the argument types
@@ -91,21 +88,14 @@ def CFUNCTYPE(restype, *argtypes, **kw):
prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal
prototype((function name, dll object)[, paramflags]) -> foreign function exported by name
"""
- flags = _FUNCFLAG_CDECL
- if kw.pop("use_errno", False):
- flags |= _FUNCFLAG_USE_ERRNO
- if kw.pop("use_last_error", False):
- flags |= _FUNCFLAG_USE_LASTERROR
- if kw:
- raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
try:
- return _c_functype_cache[(restype, argtypes, flags)]
+ return _c_functype_cache[(restype, argtypes)]
except KeyError:
class CFunctionType(_CFuncPtr):
_argtypes_ = argtypes
_restype_ = restype
- _flags_ = flags
- _c_functype_cache[(restype, argtypes, flags)] = CFunctionType
+ _flags_ = _FUNCFLAG_CDECL
+ _c_functype_cache[(restype, argtypes)] = CFunctionType
return CFunctionType
if _os.name in ("nt", "ce"):
@@ -116,23 +106,16 @@ if _os.name in ("nt", "ce"):
_FUNCFLAG_STDCALL = _FUNCFLAG_CDECL
_win_functype_cache = {}
- def WINFUNCTYPE(restype, *argtypes, **kw):
+ def WINFUNCTYPE(restype, *argtypes):
# docstring set later (very similar to CFUNCTYPE.__doc__)
- flags = _FUNCFLAG_STDCALL
- if kw.pop("use_errno", False):
- flags |= _FUNCFLAG_USE_ERRNO
- if kw.pop("use_last_error", False):
- flags |= _FUNCFLAG_USE_LASTERROR
- if kw:
- raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
try:
- return _win_functype_cache[(restype, argtypes, flags)]
+ return _win_functype_cache[(restype, argtypes)]
except KeyError:
class WinFunctionType(_CFuncPtr):
_argtypes_ = argtypes
_restype_ = restype
- _flags_ = flags
- _win_functype_cache[(restype, argtypes, flags)] = WinFunctionType
+ _flags_ = _FUNCFLAG_STDCALL
+ _win_functype_cache[(restype, argtypes)] = WinFunctionType
return WinFunctionType
if WINFUNCTYPE.__doc__:
WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
@@ -141,7 +124,6 @@ elif _os.name == "posix":
from _ctypes import dlopen as _dlopen
from _ctypes import sizeof, byref, addressof, alignment, resize
-from _ctypes import get_errno, set_errno
from _ctypes import _SimpleCData
def _check_size(typ, typecode=None):
@@ -331,24 +313,12 @@ class CDLL(object):
Calling the functions releases the Python GIL during the call and
reacquires it afterwards.
"""
- _func_flags_ = _FUNCFLAG_CDECL
- _func_restype_ = c_int
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_CDECL
+ _restype_ = c_int # default, can be overridden in instances
- def __init__(self, name, mode=DEFAULT_MODE, handle=None,
- use_errno=False,
- use_last_error=False):
+ def __init__(self, name, mode=DEFAULT_MODE, handle=None):
self._name = name
- flags = self._func_flags_
- if use_errno:
- flags |= _FUNCFLAG_USE_ERRNO
- if use_last_error:
- flags |= _FUNCFLAG_USE_LASTERROR
-
- class _FuncPtr(_CFuncPtr):
- _flags_ = flags
- _restype_ = self._func_restype_
- self._FuncPtr = _FuncPtr
-
if handle is None:
self._handle = _dlopen(self._name, mode)
else:
@@ -378,7 +348,9 @@ class PyDLL(CDLL):
access Python API functions. The GIL is not released, and
Python exceptions are handled correctly.
"""
- _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
+ _restype_ = c_int # default, can be overridden in instances
if _os.name in ("nt", "ce"):
@@ -386,7 +358,9 @@ if _os.name in ("nt", "ce"):
"""This class represents a dll exporting functions using the
Windows stdcall calling convention.
"""
- _func_flags_ = _FUNCFLAG_STDCALL
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_STDCALL
+ _restype_ = c_int # default, can be overridden in instances
# XXX Hm, what about HRESULT as normal parameter?
# Mustn't it derive from c_long then?
@@ -410,8 +384,9 @@ if _os.name in ("nt", "ce"):
HRESULT error values are automatically raised as WindowsError
exceptions.
"""
- _func_flags_ = _FUNCFLAG_STDCALL
- _func_restype_ = HRESULT
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_STDCALL
+ _restype_ = HRESULT
class LibraryLoader(object):
def __init__(self, dlltype):
@@ -449,7 +424,6 @@ if _os.name in ("nt", "ce"):
GetLastError = windll.kernel32.GetLastError
else:
GetLastError = windll.coredll.GetLastError
- from _ctypes import get_last_error, set_last_error
def WinError(code=None, descr=None):
if code is None:
diff --git a/Lib/ctypes/test/test_errno.py b/Lib/ctypes/test/test_errno.py
deleted file mode 100644
index b80656b..0000000
--- a/Lib/ctypes/test/test_errno.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import unittest, os, errno
-from ctypes import *
-from ctypes.util import find_library
-import threading
-
-class Test(unittest.TestCase):
- def test_open(self):
- libc_name = find_library("c")
- if libc_name is not None:
- libc = CDLL(libc_name, use_errno=True)
- if os.name == "nt":
- libc_open = libc._open
- else:
- libc_open = libc.open
-
- libc_open.argtypes = c_char_p, c_int
-
- self.failUnlessEqual(libc_open("", 0), -1)
- self.failUnlessEqual(get_errno(), errno.ENOENT)
-
- self.failUnlessEqual(set_errno(32), errno.ENOENT)
- self.failUnlessEqual(get_errno(), 32)
-
-
- def _worker():
- set_errno(0)
-
- libc = CDLL(libc_name, use_errno=False)
- if os.name == "nt":
- libc_open = libc._open
- else:
- libc_open = libc.open
- libc_open.argtypes = c_char_p, c_int
- self.failUnlessEqual(libc_open("", 0), -1)
- self.failUnlessEqual(get_errno(), 0)
-
- t = threading.Thread(target=_worker)
- t.start()
- t.join()
-
- self.failUnlessEqual(get_errno(), 32)
- set_errno(0)
-
- if os.name == "nt":
-
- def test_GetLastError(self):
- dll = WinDLL("kernel32", use_last_error=True)
- GetModuleHandle = dll.GetModuleHandleA
- GetModuleHandle.argtypes = [c_wchar_p]
-
- self.failUnlessEqual(0, GetModuleHandle("foo"))
- self.failUnlessEqual(get_last_error(), 126)
-
- self.failUnlessEqual(set_last_error(32), 126)
- self.failUnlessEqual(get_last_error(), 32)
-
- def _worker():
- set_last_error(0)
-
- dll = WinDLL("kernel32", use_last_error=False)
- GetModuleHandle = dll.GetModuleHandleW
- GetModuleHandle.argtypes = [c_wchar_p]
- GetModuleHandle("bar")
-
- self.failUnlessEqual(get_last_error(), 0)
-
- t = threading.Thread(target=_worker)
- t.start()
- t.join()
-
- self.failUnlessEqual(get_last_error(), 32)
-
- set_last_error(0)
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
index 830f668..bec0980 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -72,9 +72,6 @@ Extension Modules
Library
-------
-- Issue #1798: Add ctypes calling convention that allows safe access
- to errno.
-
- Patch #2125: Add GetInteger and GetString methods for
msilib.Record objects.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 7deb3f3..740b7f6 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -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");
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index 78c7419..b78c528 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -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,
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index aa297af..95b2709 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -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},
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index a7c3562..1a104cf 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -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
/*