Extending Unpadded to Python

Unpadded API can be extended to Python quite easily, allowing you to communicate with C++ application from a Python script.

Exposing keyrings and dispatchers to Python

Unpadded classes can be made available to Python inside a pybind11 module. Two classes can be exposed at the moment:

When exposing a keyring to Python, a Python module attribute is defined for each key in the keyring. The name of each attribute is the name of the function associated with the exposed key.

Please refer to the API documentation for further detail on the exposed classes interface.

Lazily compile your Python extension modules

Unpadded uses the cppimport API to allow you to import your uncompiled extension modules as if they were Python modules. If you already has some experience of cppimport, the syntax of your Mako headers will be pretty simillar. The only difference is that you will need to replace setup_pybind11(cfg) by setup_unpadded(cfg).

Note

Lazily compile extension modules will also require ccache to be installed on your computer. Theroretically, it is not needed to compile your extension modules. However, Unpadded relies on ccache to check whether the extension module needs to be recompiled. cppimport has a similar mecanism, but has to be provided an explicit list of dependencies that needs to be kept updated, so it has not been retained for Unpadded.

API References

unpack_keyring

template<typename Keyring>
void upd::py::unpack_keyring(pybind11::module &pymodule, Keyring keyring)

Expose every key template instances from a keyring to Python.

For every key in the provided keyring, a Python class with the same name as the callback held by the key will be defined with the following methods :

  • encode(self, *args) -> bytes : serialize an argument list into a sequence of bytes

  • decode(self, payload: bytes) : deserialize a sequence of bytes and return the corresponding value

  • index(self) -> int : get the index associated with the key

Template Parameters:

Keyring – Keyring holding the keys to expose

Parameters:

pymodule – Python module inside of which the classes will be defined

declare_dispatcher

template<typename Keyring>
void upd::py::declare_dispatcher(pybind11::module &pymodule, const char *name, Keyring keyring)

Expose a double_buffered_dispatcher template instance made from the given keyring.

The class will have the following methods :

  • read_from(self, getter: Callable[[], int]) -> unpadded.PacketStatus: read from a byte getter until a packet is dropped on resolved

  • write_to(self, putter: Callable[[int], None]) -> None: write to a byte putter until the internal output buffer is exhausted

  • put(self, x: int) -> None: put a single byte into the input internal buffer and return the status of the current packet

  • get(self) -> int: get a single byte from the ouput interna buffer

  • is_loaded(self) -> bool: check whether a packet is loaded in the output buffer

  • replace(self, key, f: Callable) -> None: replace the behavior of the action designated by key by f (Python callbacks are supported)

Note

The provided keyring is unpacked.

Template Parameters:

Keyring – Keyring holding the keys to expose

Parameters:
  • name – Name for the Python class bound to the dispatcher

  • pymodule – Python module inside of which the classes will be defined