CircuitPython (like MicroPython from which it derives) is implemented in C. While fundamentally different and far more complex than a typical Arduino sketch, it's still the same language; if you are comfortable work in C/C++ in the context of Arduino, CircuitPython internals should look somewhat familiar.  While it's true that we can do pretty much anything in Python, there are a variety of reasons we might want to implement a module in C as part of the virtual machine.

  1. We're running out of RAM for our Python code
  2. We have some code that needs to run faster
  3. We have some C code that we want to use.
  4. We want finer, more direct control over some aspects of the hardware.
  5. We have some functionality that is so fundamental that we always want available. digitalio is a prime example of this.


To make this happen, not only do we need to implement a Python module in C, we have to connect it to the runtime as well as add it to the build system.

In this guide we will explore how to do this. We'll start with a simple example to show what's needed, and follow that up with a more practical example of an input pin debouncer. Both of these examples are generic CircuitPython extensions, requiring no port specific code. We'll explore that in a future guide.

There isn't much documentation to be found on how to extend the runtime. The best approach after working thought this guide is to look around at the other modules defined this way and see how things are done there.

You will need to be set up and comfortable building CircuitPython for whatever board(s) you have. There's a guide to get up to speed on that.

The code in this guide has been updated to work with latest CircuitPython 4.0 from github as of mid January 2018 and will not work on prior versions.
This guide was first published on Nov 15, 2018. It was last updated on Nov 15, 2018. This page (Overview) was last updated on Jan 18, 2019.