[Python-Dev] marshal (was:Buffer interface in abstract.c? )
M.-A. Lemburg
mal@lemburg.com
Sun, 15 Aug 1999 10:59:21 +0200
David Ascher wrote:
>
> On Sat, 14 Aug 1999, Greg Stein wrote:
>
> > Having class instances respond to the buffer interface is interesting,
> > but until more code attempts to *use* the interface, I'm not quite sure
> > of the utility...
>
> Well, here's an example from my work today. Maybe someone can suggest an
> alternative that I haven't seen.
>
> I'm using buffer objects to pass pointers to structs back and forth
> between Python and Windows (Win32's GUI scheme involves sending messages
> to functions with, oftentimes, addresses of structs as arguments, and
> expect the called function to modify the struct directly -- similarly, I
> must call Win32 functions w/ pointers to memory that Windows will modify,
> and be able to read the modified memory). With 'raw' buffer object
> manipulation (after exposing the PyBuffer_FromMemoryReadWrite call to
> Python), this works fine [*]. So far, no instances.
So that's why you were suggesting that struct.pack returns a buffer
rather than a string ;-)
Actually, I think you could use arrays to do the trick right now,
because they are writeable (unlike strings). Until creating
writeable buffer objects becomes possible that is...
> I also have a class which allows the user to describe the buffer memory
> layout in a natural way given the C struct, and manipulate the buffer
> layout w/ getattr/setattr. For example:
>
> class Win32MenuItemStruct(AutoStruct):
> #
> # for each slot, specify type (maps to a struct.pack specifier),
> # name (for setattr/getattr behavior) and optional defaults.
> #
> table = [(UINT, 'cbSize', AutoStruct.sizeOfStruct),
> (UINT, 'fMask', MIIM_STRING | MIIM_TYPE | MIIM_ID),
> (UINT, 'fType', MFT_STRING),
> (UINT, 'fState', MFS_ENABLED),
> (UINT, 'wID', None),
> (HANDLE, 'hSubMenu', 0),
> (HANDLE, 'hbmpChecked', 0),
> (HANDLE, 'hbmpUnchecked', 0),
> (DWORD, 'dwItemData', 0),
> (LPSTR, 'name', None),
> (UINT, 'cch', 0)]
>
> AutoStruct has machinery which allows setting of buffer slices by slot
> name, conversion of numeric types, etc. This is working well.
>
> The only hitch is that to send the buffer to the SWIG'ed function call, I
> have three options, none ideal:
>
> 1) define a __str__ method which makes a string of the buffer and pass
> that to the function which expects an "s#" argument. This send
> a copy of the data, not the address. As a result, this works
> well for structs which I create from scratch as long as I don't need
> to see any changes that Windows might have performed on the memory.
>
> 2) send the instance but make up my own 'get-the-instance-as-buffer'
> API -- complicates extension module code.
>
> 3) send the buffer attribute of the instance instead of the instance --
> complicates Python code, and the C code isn't trivial because there
> is no 'buffer' typecode for PyArg_ParseTuple().
>
> If I could define an
>
> def __aswritebuffer__
>
> and if there was a PyArg_ParseTuple() typecode associated with read/write
> buffers (I nominate 'w'!), I believe things would be simpler -- I could
> then send the instance, specify in the PyArgParse_Tuple that I want a
> pointer to memory, and I'd be golden.
>
> What did I miss?
Just a naming thingie: __getwritebuffer__ et al. would map to the
C interfaces more directly.
The new typecode "w#" for writeable buffer style objects is a good idea
(it should only work on single segment buffers).
--
Marc-Andre Lemburg
______________________________________________________________________
Y2000: 138 days left
Business: http://www.lemburg.com/
Python Pages: http://www.lemburg.com/python/