diff options
author | Thomas Heller <theller@ctypes.org> | 2006-03-17 15:52:58 (GMT) |
---|---|---|
committer | Thomas Heller <theller@ctypes.org> | 2006-03-17 15:52:58 (GMT) |
commit | b03cb602e800efea164c7455344de13dfea37b55 (patch) | |
tree | e1d4fbef168daefbc2f4ccea71bfd7d97f9f8459 /Modules | |
parent | f4b066084a14194586399452baf05e050d58122c (diff) | |
download | cpython-b03cb602e800efea164c7455344de13dfea37b55.zip cpython-b03cb602e800efea164c7455344de13dfea37b55.tar.gz cpython-b03cb602e800efea164c7455344de13dfea37b55.tar.bz2 |
Merge changes from the upstream version:
- cast is implemented as a foreign function now
- On Windows, it is now possible to access functions exported by ordinal only
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 93 | ||||
-rw-r--r-- | Modules/_ctypes/callproc.c | 64 |
2 files changed, 81 insertions, 76 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 604c590..0be8f69 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2388,6 +2388,11 @@ static PPROC FindAddress(void *handle, char *name, PyObject *type) address = (PPROC)GetProcAddress(handle, name); if (address) return address; + + if (((size_t)name & ~0xFFFF) == 0) { + return NULL; + } + /* It should not happen that dict is NULL, but better be safe */ if (dict==NULL || dict->flags & FUNCFLAG_CDECL) return address; @@ -2493,6 +2498,28 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags) return 1; } +static int +_get_name(PyObject *obj, char **pname) +{ +#ifdef MS_WIN32 + if (PyInt_Check(obj) || PyLong_Check(obj)) { + /* We have to use MAKEINTRESOURCEA for Windows CE. + Works on Windows as well, of course. + */ + *pname = MAKEINTRESOURCEA(PyInt_AsUnsignedLongMask(obj) & 0xFFFF); + return 1; + } +#endif + if (PyString_Check(obj) || PyUnicode_Check(obj)) { + *pname = PyString_AsString(obj); + return pname ? 1 : 0; + } + PyErr_SetString(PyExc_TypeError, + "function name must be string or integer"); + return 0; +} + + static PyObject * CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -2504,7 +2531,7 @@ CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) void *handle; PyObject *paramflags = NULL; - if (!PyArg_ParseTuple(args, "sO|O", &name, &dll, ¶mflags)) + if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, ¶mflags)) return NULL; if (paramflags == Py_None) paramflags = NULL; @@ -2529,9 +2556,14 @@ CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) #ifdef MS_WIN32 address = FindAddress(handle, name, (PyObject *)type); if (!address) { - PyErr_Format(PyExc_AttributeError, - "function '%s' not found", - name); + if ((size_t)name & ~0xFFFF) + PyErr_Format(PyExc_AttributeError, + "function '%s' not found", + name); + else + PyErr_Format(PyExc_AttributeError, + "function ordinal %d not found", + name); return NULL; } #else @@ -2608,8 +2640,9 @@ CFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) "O" - must be a callable, creates a C callable function two or more argument forms (the third argument is a paramflags tuple) - "sO|O" - function name, dll object (with an integer handle) - "is|O" - vtable index, method name, creates callable calling COM vtbl + "(sO)|..." - (function name, dll object (with an integer handle)), paramflags + "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags + "is|..." - vtable index, method name, creates callable calling COM vtbl */ static PyObject * CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -2622,14 +2655,13 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (PyTuple_GET_SIZE(args) == 0) return GenericCData_new(type, args, kwds); - /* Shouldn't the following better be done in __init__? */ - if (2 <= PyTuple_GET_SIZE(args)) { + if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0))) + return CFuncPtr_FromDll(type, args, kwds); + #ifdef MS_WIN32 - if (PyInt_Check(PyTuple_GET_ITEM(args, 0))) - return CFuncPtr_FromVtblIndex(type, args, kwds); + if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0))) + return CFuncPtr_FromVtblIndex(type, args, kwds); #endif - return CFuncPtr_FromDll(type, args, kwds); - } if (1 == PyTuple_GET_SIZE(args) && (PyInt_Check(PyTuple_GET_ITEM(args, 0)) @@ -4351,6 +4383,42 @@ string_at(const char *ptr, Py_ssize_t size) return PyString_FromStringAndSize(ptr, size); } +static int +cast_check_pointertype(PyObject *arg) +{ + StgDictObject *dict; + + if (PointerTypeObject_Check(arg)) + return 1; + dict = PyType_stgdict(arg); + if (dict) { + if (PyString_Check(dict->proto) + && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) { + /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ + return 1; + } + } + PyErr_Format(PyExc_TypeError, + "cast() argument 2 must be a pointer type, not %s", + PyType_Check(arg) + ? ((PyTypeObject *)arg)->tp_name + : arg->ob_type->tp_name); + return 0; +} + +static PyObject * +cast(void *ptr, PyObject *ctype) +{ + CDataObject *result; + if (0 == cast_check_pointertype(ctype)) + return NULL; + result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL); + if (result == NULL) + return NULL; + /* Should we assert that result is a pointer type? */ + memcpy(result->b_ptr, &ptr, sizeof(void *)); + return (PyObject *)result; +} #ifdef CTYPES_UNICODE static PyObject * @@ -4486,6 +4554,7 @@ init_ctypes(void) PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset)); PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at)); + PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast)); #ifdef CTYPES_UNICODE PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at)); #endif diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 9d9e322..c019af7 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1423,71 +1423,7 @@ set_conversion_mode(PyObject *self, PyObject *args) } #endif -static char cast_doc[] = -"cast(cobject, ctype) -> ctype-instance\n\ -\n\ -Create an instance of ctype, and copy the internal memory buffer\n\ -of cobject to the new instance. Should be used to cast one type\n\ -of pointer to another type of pointer.\n\ -Doesn't work correctly with ctypes integers.\n"; - -static int cast_check_pointertype(PyObject *arg, PyObject **pobj) -{ - StgDictObject *dict; - - if (PointerTypeObject_Check(arg)) { - *pobj = arg; - return 1; - } - dict = PyType_stgdict(arg); - if (dict) { - if (PyString_Check(dict->proto) - && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) { - /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ - *pobj = arg; - return 1; - } - } - if (PyType_Check(arg)) { - PyErr_Format(PyExc_TypeError, - "cast() argument 2 must be a pointer type, not %s", - ((PyTypeObject *)arg)->tp_name); - } else { - PyErr_Format(PyExc_TypeError, - "cast() argument 2 must be a pointer type, not a %s", - arg->ob_type->tp_name); - } - return 0; -} - -static PyObject *cast(PyObject *self, PyObject *args) -{ - PyObject *obj, *ctype; - struct argument a; - CDataObject *result; - - /* We could and should allow array types for the second argument - also, but we cannot use the simple memcpy below for them. */ - if (!PyArg_ParseTuple(args, "OO&:cast", &obj, &cast_check_pointertype, &ctype)) - return NULL; - if (-1 == ConvParam(obj, 1, &a)) - return NULL; - result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL); - if (result == NULL) { - Py_XDECREF(a.keep); - return NULL; - } - // result->b_size - // a.ffi_type->size - memcpy(result->b_ptr, &a.value, - min(result->b_size, (int)a.ffi_type->size)); - Py_XDECREF(a.keep); - return (PyObject *)result; -} - - PyMethodDef module_methods[] = { - {"cast", cast, METH_VARARGS, cast_doc}, #ifdef CTYPES_UNICODE {"set_conversion_mode", set_conversion_mode, METH_VARARGS, set_conversion_mode_doc}, #endif |