Run A C/C++ Interpreter on Your ARM-based Board

Use a C/C++ REPL to have an interactive development experience like microPython, but with no limitation in APIs!

Public Chat
Similar projects worth following
The development of softwares involving interaction with peripherals could be tough, especially when you are hacking a piece of hardware you barely know anything about. In this scenario, programming hardware dynamically and interactively would be desirable. You may have already played with microPython and enjoyed the interactive experience it brought. What if you can have the same experience with C/C++ on your ARM SBC, which provides all APIs you can access as a regular C/C ++ program can?

An Interpreter, for C++?

Yes. Despite it's widely known that C++ is an AOT language, such an amazing thing as a C++ interpreter does exist. It's cling developed by Root Team of CERN on the top of LLVM and Clang. You may have played with some toy-like C interpreter already, but cling is a sophisticated project with all features a modern REPL for a regular script language is supposed to have, such as stack trace, variable shadowing and statement value echo back.

It's a shame that the official builds for cling are only available for x86/64 platforms currently, however, I managed to build it for the armhf (arm v7) architecture with a QEMU+chroot environment. Here is the repository containing the build script and a pre-compiled binary in release:

Sonuds Interesting, But Why Bother?

Cling is one of the most imaginative projects I have ever seen. How useful it is depends on how creative you are. But here I'd like to specially address on its usage on embedded development. Accessing peripherals on a SoC is essentially wrapped by system calls, and only language can handle this easily is C. The compatibility with C of cling makes it able to execute system calls directly, which essentially implies you can do anything (allowed in user space) with it, dynamically and interactively. Granted, there are frameworks like microPython which allows you to interact with peripherals dynamically as well, but this is limited to those APIs already wrapped by the framework. In comparison, you can do anything a C program can do in user space with cling. Additionally, some performance-sensitive applications are preferably written in C/C++, and a REPL is desirable for fast-prototyping and debugging.

The text wall is tiresome. Let's see an example demonstrating interact with the new GPIO API, libgpiod, dynamically with cling:

A Quick Start for Cling

hello world:

[cling]$ #include <stdio.h>
[cling]$ printf("hello world\n");
hello world

 You can include all headers contained in the search path of your system, including kernel headers. All symbols are ready to use after the include statement.

Echo Values of Statements:

What if you omit the semicolon at the end of a statement? Will you get an error? No, cling will echo the value of that statement in this condition. People have worked with matlab may feel familiar with this: If the ending semicolon isn't omitted, the echo in the console will be disabled, otherwise the echo will be printed:

[cling]$ __cplusplus
(long) 201703

Cling can echo statements of  some objects and their references analytically. The supported objects are mainly STL containers:

[cling]$ #include <string>
[cling]$ std::string {"str"}
(std::string) "str"
[cling]$ #include <vector>
[cling]$ std::vector<char> ve{'c', 'h', 'a', 'r'} 
(std::vector<char> &) { 'c', 'h', 'a', 'r' }
[cling]$ #include <map>
[cling]$ std::map<int, char> mp{std::pair<int,char>()}
(std::map<int, char> &) { 0 => '0x00' }

Names of functions are also statements. What values will be echoed for them?

[cling]$ atoi
(int (*)(const char *) throw()) Function @0xb6c7bcd1
  at /usr/include/stdlib.h:104:
extern int atoi (const char *__nptr)
     __THROW __attribute_pure__ __nonnull ((1))

It's the signature of the function!

I enabled RTTI in my build script, so the dynamic inspection of types by typeid is also supported:

[cling]$ auto b = std::string ("typed")
(std::basic_string<char, std::char_traits<char>, std::allocator<char> > &) "typed"
[cling]$ typeid(b).name()
(const char *) "NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"

To convert this mangled type name to readable text, you may want to use c++filt:

c++filt _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >

Advanced Usages

Loading Files

Except standard C++ syntax, cling...

Read more »

View all 4 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates