Dgram in c++ is wrapped and made available in Python via psana.dgram module. For a general developer use case, a Dgram can be created by passing a file descriptor or an Python object that implements buffer interface (e.g. memoryview, bytearray, bytes, np.array, etc). In a more advance developer use case such as dealing with Cython, many times a c++ Dgram is used interchangeably with the Python one. This document summarizes a few possible ways to convert to and from the two languages.

From Python objects to C++ Dgram

These Python objects include psana.dgram.Dgram class and any other types of Python object that implements the buffer interface. In the Cython code below, we assume that c++ Dgram is wrapped made available in Cython module (click here for example of wrapping C++ class) and view is any buffer object with dgram data in it.

from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_ANY_CONTIGUOUS, PyBUF_SIMPLE

def from_py_to_c(view):
    cdef Dgram* d
    cdef char* view_ptr
    cdef Py_buffer buf
    
	# Use the pythonc interface to obtain the buffer that the Python object owns.
    PyObject_GetBuffer(view, &buf, PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS)
    view_ptr = <char *>buf.buf

    # Cast to our Dgram pointer
    d = <Dgram *>(view_ptr)
    
    # Access the c++ Dgram 
    print(d.xtc.extent)

    # Release the buffer when done
    PyBuffer_Release(&buf)

Note that you can iterate through a list of dgrams that are stored consecutively in view (if any). This is done by simply increasing the view_ptr with the size of the current dgram.

cdef size_t payload = 0
payload = d.xtc.extent - sizeof(Xtc)
view_ptr += sizeof(Dgram) + payload

From C++ Dgram to Python

Python Dgram object can be created in two ways:

  1. Using file descriptor: This way, a memory space is allocated and deallocated by the Dgram class.
  2. Using view (ant buffer-interface Python objects): Dgram class handles reference count for the given view object. 

One way to cleanly pass a C++ Dgram to Python is to copy the contents to a buffer-interface object and create a Python Dgram from it. With this method, the life-time of the memory location is handled by the Python Dgram class. 

  • No labels