diff options
author | Thomas Heller <theller@ctypes.org> | 2008-04-25 15:44:16 (GMT) |
---|---|---|
committer | Thomas Heller <theller@ctypes.org> | 2008-04-25 15:44:16 (GMT) |
commit | 6ad5fbb7ea90d475d77ee3b41a6ba198316b0d05 (patch) | |
tree | fef0c3cc8ea18ee7ea044abb324af6a6932dad0b /Modules | |
parent | 5364e2e46f7566e1917d013f83c431a72de76009 (diff) | |
download | cpython-6ad5fbb7ea90d475d77ee3b41a6ba198316b0d05.zip cpython-6ad5fbb7ea90d475d77ee3b41a6ba198316b0d05.tar.gz cpython-6ad5fbb7ea90d475d77ee3b41a6ba198316b0d05.tar.bz2 |
Add from_buffer and from_buffer_copy class methods to ctypes types.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c9da7d3..1bb76e3 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -412,6 +412,115 @@ CDataType_from_address(PyObject *type, PyObject *value) return CData_AtAddress(type, buf); } +static char from_buffer_doc[] = +"C.from_buffer(object, offset=0) -> C instance\ncreate a C instance from a writeable buffer"; + +static int +KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep); + +static PyObject * +CDataType_from_buffer(PyObject *type, PyObject *args) +{ + void *buffer; + Py_ssize_t buffer_len; + Py_ssize_t offset = 0; + PyObject *obj, *result; + StgDictObject *dict = PyType_stgdict(type); + assert (dict); + + if (!PyArg_ParseTuple(args, +#if (PY_VERSION_HEX < 0x02050000) + "O|i:from_buffer", +#else + "O|n:from_buffer", +#endif + &obj, &offset)) + return NULL; + + if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len)) + return NULL; + + if (offset < 0) { + PyErr_SetString(PyExc_ValueError, + "offset cannit be negative"); + return NULL; + } + if (dict->size > buffer_len - offset) { + PyErr_Format(PyExc_ValueError, +#if (PY_VERSION_HEX < 0x02050000) + "Buffer size too small (%d instead of at least %d bytes)", +#else + "Buffer size too small (%zd instead of at least %zd bytes)", +#endif + buffer_len, dict->size + offset); + return NULL; + } + + result = CData_AtAddress(type, (char *)buffer + offset); + if (result == NULL) + return NULL; + + Py_INCREF(obj); + if (-1 == KeepRef((CDataObject *)result, -1, obj)) { + Py_DECREF(result); + return NULL; + } + return result; +} + +static char from_buffer_copy_doc[] = +"C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer"; + +static PyObject * +GenericCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); + +static PyObject * +CDataType_from_buffer_copy(PyObject *type, PyObject *args) +{ + void *buffer; + Py_ssize_t buffer_len; + Py_ssize_t offset = 0; + PyObject *obj, *result; + StgDictObject *dict = PyType_stgdict(type); + assert (dict); + + if (!PyArg_ParseTuple(args, +#if (PY_VERSION_HEX < 0x02050000) + "O|i:from_buffer", +#else + "O|n:from_buffer", +#endif + &obj, &offset)) + return NULL; + + if (-1 == PyObject_AsReadBuffer(obj, &buffer, &buffer_len)) + return NULL; + + if (offset < 0) { + PyErr_SetString(PyExc_ValueError, + "offset cannit be negative"); + return NULL; + } + + if (dict->size > buffer_len - offset) { + PyErr_Format(PyExc_ValueError, +#if (PY_VERSION_HEX < 0x02050000) + "Buffer size too small (%d instead of at least %d bytes)", +#else + "Buffer size too small (%zd instead of at least %zd bytes)", +#endif + buffer_len, dict->size + offset); + return NULL; + } + + result = GenericCData_new((PyTypeObject *)type, NULL, NULL); + if (result == NULL) + return NULL; + memcpy(((CDataObject *)result)->b_ptr, + (char *)buffer+offset, dict->size); + return result; +} + static char in_dll_doc[] = "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"; @@ -516,6 +625,8 @@ CDataType_from_param(PyObject *type, PyObject *value) static PyMethodDef CDataType_methods[] = { { "from_param", CDataType_from_param, METH_O, from_param_doc }, { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, { NULL, NULL }, }; @@ -845,6 +956,8 @@ PointerType_from_param(PyObject *type, PyObject *value) static PyMethodDef PointerType_methods[] = { { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, { "from_param", (PyCFunction)PointerType_from_param, METH_O, from_param_doc}, { "set_type", (PyCFunction)PointerType_set_type, METH_O }, @@ -1859,6 +1972,8 @@ SimpleType_from_param(PyObject *type, PyObject *value) static PyMethodDef SimpleType_methods[] = { { "from_param", SimpleType_from_param, METH_O, from_param_doc }, { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, { NULL, NULL }, }; |