Making C++ wrapper libraries for Swift for Arduino - part 1

I have just started adding a library to use the Adafruit Bluefruit LE, which is a great little shield made by Adafruit. Problem is, as ever, their software they give away is to make the shield work with Arduino/C++. What to do?

Since version 2.9 of Swift for Arduino, it has been possible to use a special category of library files in addition to the usual ones from the community github site.

Just like the usual library files, these are of the form XXX.swift, are all kept in the github community site for general use (https://github.com/swiftforarduino/community see the community libraries).

This new type are named unsafeXXX.swift to be clear that they contain a core of unsafe C++ (usually legacy) code. In nearly every case, the code could be ported to pure swift at some point but it can be a lot of work, so in order to make it possible to get up and running faster and to leverage existing legacy code, it can be wrapped in Swift.

The basic way this works is this:

1) make a new project in the community site in contributed unsafe libraries, usually copying an existing project and modifying it

2) copy in the legacy code with the C++ classes that you want to wrap, then update the module file, makefile and create a cpp/h pair for the specialised "wrapper" class, often by modifying the existing one from another library... this class will have a header file containing declarations in an extern "C" {} block and matching definitions in the class body. Each is usually just a wrapper around a call to methods in the c++ class(es) that you're trying to wrap. This just exposes the functionality in standard C. The header file will be included in the module.modmap file to define it as part of a clang module.

3) The unsafeXXX.swift file will usually then just expose these definitions to swift and clean up any interface mismatch. While this is not strictly essential, it makes for cleaner interfacing and creates a natural extension point where simple functionality can be ported to swift or other furniture like deprecated methods, etc. might exist. You might have specific reasons you don't want this (e.g. in super high performance code) but generally it's probably best to follow this pattern.

4) Finally you will probably need to adapt the imported C++ code. This can be the slowest and most complicated bit. Many or most of these classes are not truly standalone and depend on things like Arduino libraries support for hardware interactions (SPI, I2C, digital write, UART, ADC). This is done differently in Swift for Arduino as we have a completely unique and different core library.

Challenges... my diary of progress...

In the case of the Adafruit Bluefruit code that I imported, it inherits from the Stream class, which inherits from Print, meaning it would import all the extra overhead of the Arduino String class, among other things.

To fix this, instead I copied in the arduino classes Stream and Print and removed a lot of stuff from them. In particular, I removed all references to the String class, so only classic C strings/character buffers and their PROGMEM equivalent are supported.






Comments

Popular posts from this blog

Halloween LED lights on a plastic trick or treat cauldron

All about bootloaders

code signing, entitlements, bundles, sandboxes, hardened runtime, notarisation, app store security