This module provides three classes: Block, View, and Readview. A block is an allocated chunk of memory that exists (at one address) for the whole time a reference to the block is maintained. Blocks are allocated either by Block(N), where N is the size, in bytes, of the allocated memory, or by Block(str), where str is a byte string whose length will be the size of the block, and whose bytes will serve as the initial contents of the block. Normally there are no operations on blocks, access to the data is normally via views. Blocks may not be subclassed.

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:

  • 'c' single byte character
  • 'u' single Unicode character (where applicable)
  • 'b' signed one-byte integer
  • 'B' unsigned one-byte integer
  • 'h' signed short integer
  • 'H' unsigned short integer
  • 'i' signed integer
  • 'I' unsigned integer
  • 'l' signed long integer
  • 'L' unsigned long integer
  • 'q' signed long long integer (where applicable)
  • 'Q' unsigned long long integer (where applicable)
  • 'f' float
  • 'd' double
  • 'F' complex (pair of floats)
  • 'D' complex (pair of doubles) Note: The provided string constant, viewtypes containing all of the valid type letters for this build; it may or may not contain 'u', 'q', and/or 'Q', depending on the python instalation.

    Views are created on blocks (or other compatible views) by:

    The start, step, and stop values (if present) are in discrete elements of the type. So, on a system with 4-byte ints, after:
           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 = 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

    View or Readview:

    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

    View only

    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.