Version 0.6.
Primarily for debugging convenience, in a Block b:
A view (either a Readview or a View) is a way of examining (and in the case of a View modifying) the contents of some portion of the data memory encapsulated in a block. Views hold references to the block they examine, thus they keep the block from being recycled. A Readview behaves much like an array, with no chance for modification. A View not only provides all the operations of a Readview, but it allows non-resizing modification operations normally provided by array. Readviews and Views are created with a single datatype for the elements of the view. This type is represented by a type letter:
Views are created on blocks (or other compatible views) by:
b = Block(32)
w = View('i', b)
r = Readview('i', b, 1, 3)
w is a 4-int view of the entire block b, and r is a 2-int view
of the middle of b. w[2] and r[1] both refer to the same memory,
but that memory may only be changed via w.
vw = newview(type='c', source=None, size=None) Create a new Block of memory to hold size or len(source) elements of the specified type, create a View on that data of the appropriate type, and then initialize the storage elementwise from the data in source through the View.
block = Block(N) -- allocate an N-byte zeroed block of storage
block = Block(string) -- allocate a len(string)-byte block of storage initialized from the string.
block.length: number of bytes in memory
block._guts(): contents of block as a string
block._address: Address of the data store for this block
vw = View(type, block, start, stop, stride=1) -- block is interpretted as a vector of appropriately sized elements. The start, stop, and stride are in counts of these elements.
vw = View(type, block)
vw = View(type, view)
vw = View(compatibletype, view, start, stop, stride=1)
vw._address Address of the zeroth element of this view
vw._basis Underlying python object (a Block) containing data
vw._stride Byte distance between consecutive elements of View.
vw.typecode Type code for elements of this view
vw.itemsize size (in bytes) of storage used for one element.
vw.count(v) count the number of elements equal to v.
vw.index(v) index of first element in view equal to v.
vw.tostring() underlying bytes of view as data in string.
vw.tounicode() underlying unicode (only on appropriately sized elements)
vw.tolist() results of [view[n] for n in range(len(view))]
vw[N] Element of the view.
vw[M:N] View of same memory (subrange).
vw[M:N:S] View of same memory (subrange).
vw1 cmp vw2 : comparison between views
vw[N] = expression Assign single Element of view.
vw[M:N] = somelist assign somelist elements (sizes must match)
vw[M:N:S] = somelist assign somelist elements (sizes must match)
vw.byteswap() Reorder bytes within each view element (useless on cbB)
vw.reverse() Reorder elements within view
The _block module provides three classes and a constant: viewtypes is the constant, a string of all the valid types for a view. Block, Readview, and View are the classes. A Block represent storage. Block(integer) is that number of bytes of storage (zeroed). Block(string) is len(string) bytes of storage initialized to the contents of string.
A Readview is a read-only window into some of the bytes of a block. Readview(code, Block_or_View[, [start, ] stop]) creates such a view. Valid codes are in viewtypes. start and stop work much like range, but the units are elements of the type indicated by the code. A Writeview (a subclass of Readview) is a read/write window into some of the bytes of a block. Writeview(code, Block_or_Writeview[, [start, ] stop]) creates such a view. It works much like a Readview, but cannot be created from a read-only view of the data.
with block version 0.5 and later,
a c_viewers is a PyCObject which, when unpacked in a
C program, is a pointer to a block of pointers to C language functions:
struct s_viewers {
PyObject *(*c_reader)(char typecode, PyObject *basis,
int length, int stride, void *memory);
PyObject *(*c_writer)(char typecode, PyObject *basis,
int length, int stride, void *memory);
void *(*c_block)(PyObject **blockvar, int length);
PyObject *(*c_viewer)(char typecode, PyObject *basis,
int length, int byte_stride,
void *memory, PyObject *Type);
}
c_reader creates a Readview dependent on the provided basis object with length elements stride elements apart with the first element at memory. Reading from this view is allowed, but writing through it is not. If NULL is provided as basis, None is used.
c_writer similarly creates a View dependent on the provided basis object with length elements stride elements apart with the first element at memory. Both reading from and writing through this view are allowed. If NULL is provided as basis, None is used.
c_block allocates a block of size length (length <= 0 not allowed), and returns a pointer to the data section of that block object, while the blockvar variable is set to the PyObject * of the block. If c_block returns NULL, allocation has failed, errors have been set, and the referenced block variable *blockvar has also been set NULL.
c_viewer creates either Views or Readviews dependent on the final parameter. Most of its other arguments match those of both c_reader or c_writer, but the stride is expressed in bytes rather than elements. The C code is responsible for all alignment issues, and no care is taken when writing to overlapped elements in a group (translation: don't do that).
basis object with length elements stride elements apart with the first element at memory. Both reading from and writing through this view are allowed. If NULL is provided as basis, None is used.
The following C code may give you a sample use:
struct s_viewers *viewers = NULL;
static int arr[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int
setup(PyCObject *arg)
{
if (viewers || (viewers = PyCObject_AsVoidPtr(arg))) {
return 1;
}
PyErr_SetString(PyExc_ValueError, "No viewers set.");
return 0;
}
PyObject *
a_reader(PyObject *self, PyCObject *arg)
{
if (setup(arg)) {
return viewers->c_reader('i', NULL, 3, 2, arr);
}
return NULL;
}
PyObject *
a_writer(PyObject *self, PyCObject *arg)
{
if (setup(arg)) {
return viewers->c_writer('I',
PyExc_KeyboardInterrupt,
5, 1, &arr[1]);
}
return NULL;
}
PyObject *
a_remembered_block(PyObject *self, PyCObject *arg)
{
if (setup(arg)) {
PyObject *result;
void *my_pointer = viewers->c_block(1024);
if (my_pointer) {
/* to hold when caller forgets */
Py_INCREF(result);
start_thread_using(my_pointer);
return result;
}
}
return NULL;
}
PyObject *
a_viewer_reads(PyObject *self, PyCObject *arg)
{
if (setup(arg)) {
PyObject *result;
return viewers->c_viewer('i', NULL, 3,
2 * sizeof(int), arr, Readview);
}
return NULL;
}
Normally, there would be a single call to setup, associated with an import
of block and the module's subsequent initialization.
a_reader, when called with the module's c_viewers from python, returns a Readview referring to the three integers: arr[0], arr[2], and arr[4].
a_writer, when called with the module's c_viewers from python, returns a Writeview referring to the five integers: arr[1], arr[2], arr[3], arr[4], and arr[5]. It will hold a reference to PyExc_KeyboardInterrupt (known in python as KeyboardInterrupt) as long as this view or any subview created from it continues to exist.
a_remembered_block is a sketch of some code that wants to both use and return a block.
a_viewer_reads, Creates a read view of the same sort as a_reader, viewing exactly the same memory. Nothing here shows how this code got a copy of Readview from the block module.