summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2008-04-25 15:44:16 (GMT)
committerThomas Heller <theller@ctypes.org>2008-04-25 15:44:16 (GMT)
commit6ad5fbb7ea90d475d77ee3b41a6ba198316b0d05 (patch)
treefef0c3cc8ea18ee7ea044abb324af6a6932dad0b /Modules
parent5364e2e46f7566e1917d013f83c431a72de76009 (diff)
downloadcpython-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.c115
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 },
};