Eryk Sun added the comment:
Probably adding from_pointer is a good idea. That said, there's a simpler way
to go about getting a bytes copy for a pointer.
Say that you have a pointer p for the following array:
>>> a = (c_float * 3)(1, 2, 3)
>>> bytes(a)
b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@'
>>> p = POINTER(c_float)(a)
IMO, the most straight-forward way to get a bytes copy is to call string_at:
>>> string_at(p, sizeof(p.contents) * 3)
b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@
In 3.x string_at uses the FFI machinery to call the following function:
static PyObject *
string_at(const char *ptr, int size)
{
if (size == -1)
return PyBytes_FromStringAndSize(ptr, strlen(ptr));
return PyBytes_FromStringAndSize(ptr, size);
}
The first argument can be any type accepted by c_void_p.from_param, such as a
ctypes pointer/array, str, bytes, or an integer address.
Alternatively, note that pointer instantiation is the same as setting the
`contents` value, which accepts any ctypes data object. Here's the C code that
implements this assignment:
dst = (CDataObject *)value;
*(void **)self->b_ptr = dst->b_ptr;
The b_ptr field points at the buffer of the ctypes data object. Thus you can
cast p to a char pointer without even calling the cast() function, which avoids
an FFI call:
>>> bp = POINTER(c_char)(p.contents)
Slicing c_char and c_wchar pointers is special cased to return bytes and str,
respectively. So you can slice bp to get bytes:
>>> bp[:sizeof(p.contents) * 3]
b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@'
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue27274>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com