2002-07-29 14:22:09 -04:00
|
|
|
|
PEP: 298
|
2002-07-30 12:41:04 -04:00
|
|
|
|
Title: The Fixed Buffer Interface
|
2002-07-29 14:22:09 -04:00
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
2002-07-30 12:41:04 -04:00
|
|
|
|
Author: Thomas Heller <theller@python.net>
|
2002-07-29 14:22:09 -04:00
|
|
|
|
Status: Draft
|
|
|
|
|
Type: Standards Track
|
|
|
|
|
Created: 26-Jul-2002
|
|
|
|
|
Python-Version: 2.3
|
|
|
|
|
Post-History:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
|
|
|
|
|
This PEP proposes an extension to the buffer interface called the
|
2002-07-30 12:41:04 -04:00
|
|
|
|
'fixed buffer interface'.
|
2002-07-29 14:22:09 -04:00
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The fixed buffer interface fixes the flaws of the 'old' buffer
|
2002-07-29 14:22:09 -04:00
|
|
|
|
interface as defined in Python versions up to and including 2.2,
|
|
|
|
|
see [1]:
|
|
|
|
|
|
|
|
|
|
The lifetime of the retrieved pointer is clearly defined.
|
|
|
|
|
|
|
|
|
|
The buffer size is returned as a 'size_t' data type, which
|
|
|
|
|
allows access to large buffers on platforms where sizeof(int)
|
|
|
|
|
!= sizeof(void *).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The fixed buffer interface exposes new functions which return the
|
2002-07-29 14:22:09 -04:00
|
|
|
|
size and the pointer to the internal memory block of any python
|
|
|
|
|
object which chooses to implement this interface.
|
|
|
|
|
|
|
|
|
|
The size and pointer returned must be valid as long as the object
|
|
|
|
|
is alive (has a positive reference count). So, only objects which
|
|
|
|
|
never reallocate or resize the memory block are allowed to
|
|
|
|
|
implement this interface.
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The fixed buffer interface omits the memory segment model which is
|
2002-07-29 14:22:09 -04:00
|
|
|
|
present in the old buffer interface - only a single memory block
|
|
|
|
|
can be exposed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
|
|
|
|
|
Define a new flag in Include/object.h:
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
/* PyBufferProcs contains bf_getfixedreadbuffer
|
|
|
|
|
and bf_getfixedwritebuffer */
|
|
|
|
|
#define Py_TPFLAGS_HAVE_GETFIXEDBUFFER (1L<<15)
|
2002-07-29 14:22:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This flag would be included in Py_TPFLAGS_DEFAULT:
|
|
|
|
|
|
|
|
|
|
#define Py_TPFLAGS_DEFAULT ( \
|
|
|
|
|
....
|
2002-07-30 12:41:04 -04:00
|
|
|
|
Py_TPFLAGS_HAVE_GETFIXEDBUFFER | \
|
2002-07-29 14:22:09 -04:00
|
|
|
|
....
|
|
|
|
|
0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Extend the PyBufferProcs structure by new fields in
|
|
|
|
|
Include/object.h:
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
typedef size_t (*getfixedreadbufferproc)(PyObject *, void **);
|
|
|
|
|
typedef size_t (*getfixedwritebufferproc)(PyObject *, void **);
|
2002-07-29 14:22:09 -04:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
getreadbufferproc bf_getreadbuffer;
|
|
|
|
|
getwritebufferproc bf_getwritebuffer;
|
|
|
|
|
getsegcountproc bf_getsegcount;
|
|
|
|
|
getcharbufferproc bf_getcharbuffer;
|
2002-07-30 12:41:04 -04:00
|
|
|
|
/* fixed buffer interface functions */
|
|
|
|
|
getfixedreadbufferproc bf_getfixedreadbufferproc;
|
|
|
|
|
getfixedwritebufferproc bf_getfixedwritebufferproc;
|
2002-07-29 14:22:09 -04:00
|
|
|
|
} PyBufferProcs;
|
|
|
|
|
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The new fields are present if the Py_TPFLAGS_HAVE_GETFIXEDBUFFER
|
2002-07-29 14:22:09 -04:00
|
|
|
|
flag is set in the object's type.
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The Py_TPFLAGS_HAVE_GETFIXEDBUFFER flag implies the
|
2002-07-29 14:22:09 -04:00
|
|
|
|
Py_TPFLAGS_HAVE_GETCHARBUFFER flag.
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
The getfixedreadbufferproc and getfixedwritebufferproc functions
|
2002-07-29 14:22:09 -04:00
|
|
|
|
return the size in bytes of the memory block on success, and fill
|
|
|
|
|
in the passed void * pointer on success. If these functions fail
|
|
|
|
|
- either because an error occurs or no memory block is exposed -
|
|
|
|
|
they must set the void * pointer to NULL and raise an exception.
|
|
|
|
|
The return value is undefined in these cases and should not be
|
|
|
|
|
used.
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
Usually the getfixedwritebufferproc and getfixedreadbufferproc
|
2002-07-29 14:22:09 -04:00
|
|
|
|
functions aren't called directly, they are called through
|
|
|
|
|
convenience functions declared in Include/abstract.h:
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
int PyObject_AsFixedReadBuffer(PyObject *obj,
|
2002-07-29 14:22:09 -04:00
|
|
|
|
void **buffer,
|
|
|
|
|
size_t *buffer_len);
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
int PyObject_AsFixedWriteBuffer(PyObject *obj,
|
2002-07-29 14:22:09 -04:00
|
|
|
|
void **buffer,
|
|
|
|
|
size_t *buffer_len);
|
|
|
|
|
|
|
|
|
|
These functions return 0 on success, set buffer to the memory
|
|
|
|
|
location and buffer_len to the length of the memory block in
|
2002-07-30 12:41:04 -04:00
|
|
|
|
bytes. On failure, or if the fixed buffer interface is not
|
2002-07-29 14:22:09 -04:00
|
|
|
|
implemented by obj, they return -1 and set an exception.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Backward Compatibility
|
|
|
|
|
|
|
|
|
|
The size of the PyBufferProcs structure changes if this proposal
|
|
|
|
|
is implemented, but the type's tp_flags slot can be used to
|
|
|
|
|
determine if the additional fields are present.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Reference Implementation
|
|
|
|
|
|
|
|
|
|
Will be uploaded to the SourceForge patch manager by the author.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Additional Notes/Comments
|
|
|
|
|
|
|
|
|
|
Python strings, Unicode strings, mmap objects, and maybe other
|
2002-07-30 12:41:04 -04:00
|
|
|
|
types would expose the fixed buffer interface, but the array type
|
2002-07-29 14:22:09 -04:00
|
|
|
|
would *not*, because its memory block may be reallocated during
|
|
|
|
|
its lifetime.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Community Feedback
|
|
|
|
|
|
2002-07-30 12:41:04 -04:00
|
|
|
|
Greg Ewing doubts the fixed buffer interface is needed at all, he
|
2002-07-29 14:22:09 -04:00
|
|
|
|
thinks the normal buffer interface could be used if the pointer is
|
2002-07-30 12:41:04 -04:00
|
|
|
|
(re)fetched each time it's used. This seems to be dangerous,
|
|
|
|
|
because even innocent looking calls to the Python API like
|
|
|
|
|
Py_DECREF() may trigger execution of arbitrary Python code.
|
2002-07-29 14:22:09 -04:00
|
|
|
|
|
|
|
|
|
Neil Hodgson wants to expose pointers to memory blocks with
|
|
|
|
|
limited lifetime: do some kind of lock operation on the object,
|
2002-07-30 12:41:04 -04:00
|
|
|
|
retrieve the pointer, use it, and unlock the object again. While
|
|
|
|
|
the author sees the need for this, it cannot be addressed by this
|
|
|
|
|
proposal. Beeing required to call a function after not using the
|
2002-07-30 12:52:53 -04:00
|
|
|
|
pointer received by the getfixedbufferprocs any more seems too
|
|
|
|
|
error prone.
|
2002-07-30 12:41:04 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Credits
|
|
|
|
|
|
|
|
|
|
Scott Gilbert came up with the name 'fixed buffer interface'.
|
2002-07-29 14:22:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
References
|
|
|
|
|
|
|
|
|
|
[1] The buffer interface
|
|
|
|
|
http://mail.python.org/pipermail/python-dev/2000-October/009974.html
|
|
|
|
|
|
|
|
|
|
[2] The Buffer Problem
|
|
|
|
|
http://www.python.org/peps/pep-0296.html
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
End:
|