views:

160

answers:

1

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?

+1  A: 

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
Antoine P.
Really? Memoryviews don't do slicing? I thought that was supposed to be the big benefit of using them. Do they at least support basic indexing? The whole point of me trying to expose this memory is to allow Python developers to manipulate image data at a byte level, and if they can't do basic indexing or slicing then this method is useless to me.
Toji
See edited version above.
Antoine P.
Ah, thank you for the clarification. That's more in line with what I thought. I'll have to play with that and see if I can work out a good way of achieving what I want. Thanks again!
Toji