The cppmem module *must* be switched into MicroPython heap mode or C++ code will inevitably run out of RAM.
Thus boot.py needs to be included in every build.
This module redirects all pre-init object memory allocations into a static, fixed-sized, linear, non-freeing memory pool.
It then auto-switches into "MICROPYTHON" mode, whereupon all C++ `new` and `delete` calls are remapped to `m_malloc` and `m_free` respectively.
MicroPython's GET_STR_DATA_LEN macro returns a const byte array and len, which std::string would copy into heap.
Using string_view lets us wrap the existing const values.
Due to quirks with how QSTRs are passed, conditionally including a function is difficult.
Instead, always include "get_shift_state" but throw a RuntimeError if its use is invalid (no shift register).