Question

EDIT: Upon re-reading my original question I realized very quickly that it was very poorly worded, ambiguous, and too confusing to ever get a decent answer. That's what I get for rushing out a question at the end of my lunch break. Hopefully this will be clearer:

I am trying to expose a simple C structure to Python (3.x) as a PyBuffer so I can retrieve a MemoryView from it. The structure I want to expose is similar to this:

struct ImageBuffer {
    void* bytes;
    int row_count;
    int bytes_per_row;
};

and it is my desire to allow the script writer to access the data like so:

img_buffer = img.get_buffer()
img_buffer[1::4] = 255 # Set every Red component to full intensity

Unfortunately the existing documentation about the C API for these structures is pretty sparse, self contradictory in places, and outright wrong in others (documented function signatures do not match those in the headers, etc.) As such I don't have a very good idea about how to best expose this. Also, I would like to avoid including third party libs to achieve functionality that should be part of the core libs, but it feels to me like the PyBuffer functionality is still fairly immature, and perhaps something like NumPy would be a better choice.

Does anyone have any advice on this?

Was it helpful?

Solution

The set of methods to implement so that your extension type supports the buffer protocol is described here: http://docs.python.org/3.1/c-api/typeobj.html#buffer-object-structures

I recognize that the documentation is pretty rough, so the best advice I can give is to start from an existing implementation of the buffer API by a C type, for example bytesobject.c or bytearrayobject.c in the official Python source code.

However, please note that the buffer protocol doesn't give access to high-level notations such as the one you quoted: img_buffer[1::4] = 255 won't work on a memoryview object.

Edit: to be more precise, memoryviews support some kinds of slice assignment, but not all of them. Also, they are not "smart" enough to understand that assigning 255 to a slice actually means that you want the byte value to be repeated. Example:

>>> b = bytearray(b"abcd")
>>> m = memoryview(b)
>>> m[0:2] = b"xy"
>>> b
bytearray(b'xycd')
>>> m[0:2] = 255
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'int' does not support the buffer interface
>>> m[0:2] = b"x"
Traceback (most recent call last):
  File "", line 1, in 
ValueError: cannot modify size of memoryview object
>>> m[0::2] = b"xy"
Traceback (most recent call last):
  File "", line 1, in 
NotImplementedError
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top