Index: Modules/_ctypes/_ctypes.c =================================================================== --- Modules/_ctypes/_ctypes.c (revision 62373) +++ Modules/_ctypes/_ctypes.c (working copy) @@ -412,6 +412,54 @@ return CData_AtAddress(type, buf); } +static char from_buffer_doc[] = +"C.from_address(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 (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); + Py_INCREF(obj); + if (-1 == KeepRef((CDataObject *)result, -1, obj)) { + Py_DECREF(result); + return NULL; + } + return result; +} + static char in_dll_doc[] = "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"; @@ -516,6 +564,7 @@ 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, }, { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, { NULL, NULL }, }; @@ -845,6 +894,7 @@ static PyMethodDef PointerType_methods[] = { { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_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 +1909,7 @@ 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, }, { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, { NULL, NULL }, };