How do I invoke a C++ Arduino library from rust? - c++

It has been possible to build apps for Arduino and Teensy written in Rust for a while.
You can find lists of peripheral libraries ( https://github.com/rust-embedded/awesome-embedded-rust ) , but there are so many peripherals that it can take a while for native Rust implementations to be written for the less common ones.
In my case, I have AdaFruit Neopixels. There are a couple of C++ libraries for this ( https://github.com/Makuna/NeoPixelBus/wiki/Library-Comparisons ) , but the only Rust library I could find is https://github.com/trezm/neopixel_rs which depends on a crate with a path of ../photon-hal , and even when I remove that, I get compile errors deep in a macro which might be related to the build.rs for compiling the C++ elements. I'm not even sure it is targeting the Arduino.
Is there a document that outlines the proper procedure for cross-compiling a C++ module from the Arduino, and then wrapping it in a Rust API?

So far I have developed a crate to help me write Rust wrappers for C++ libraries. rust-arduino-helpers is a library of helper functions and as of 2022-May is almost entirely undocumented.
rust-arduino-helpers is mostly driven by the development of the rust-arduino-wrappers crate, which contains wrappers for the Ethernet, NeoPixel, and PubSubClient(MQTT) libraries.
The first step is build.rs. Use bindgen to translate the C++ header file into a Rust bindings.rs.
Then you compile the C++ library source so you can include the library in the rust app. Sometimes you create a file like src-cpp/multi.cpp which #includes the various .cpp files of the library. Alternatively, you can list the library source files as individual arguments to the file() method of the cc:Build object.
The rust-arduino-helpers crate has helper methods that help configure bindgen and the cc:Build. Then create a src/raw.rs containing something like
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
#![allow(dead_code)]
#![allow(clippy::all)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
In the raw.rs file you can add a little bit of helper code (sometimes a use clause), but the majority of your wrappers will go in lib.rs. This is where you'll create Rust wrapper structs that own pins or other devices, and ensure correct initialization and deallocation.
It may be helpful to examine some of the examples like ethernet/build.rs until there is proper documentation

Related

How to correctly implement the ROS2 architecture (rclcpp, rcl, rmw)

I am a beginner with ROS2 and C++ and I can use some help understanding how the architecture of ROS 2 works. I want to implement a QoS-event into a simple chatter program and with my basic knowledge I can make following graph:
CODE (publisher.cpp) ==> RCLCPP(qos_event.cpp) this includes (qos_event.hpp) ==> RCL (event.c) this includes (event.h) ==> RMW (event.c) this includes (event.h) ==> DDS
I have the following questions:
If I understand it right, header files are used as some kind of library. So if you include them in your program you can use all the functions you want. This means I don't need to use this code in my program but I only need to implement those functions? Are the following files: qos_event.cpp / rcl event.c / rmw event.c examples of code that I can use into my own program?
The Quality of Service (QoS) settings are declared in the Ros middleware (rmw). If I want to use one of those events, can I just directly use the rmw/event.h header file or do I need to respect the architecture and is it only possible to implement rclcpp code in your program?
1) Generally header files have declarations of functions that you can use and .c or .cpp files have the definition of them, showing how the function actually is implemented. This may be a good starting point for that. In order to use this functions in your executable or library, you have to add these dependencies via CMakeLists.txt and package.xml(a whole new world for c++ beginners).
2) About this ... I would recommend checking this git from ROS2 and studying how these functions were used.
Usually people say to study c++ before using the ROS Framework, this is a really good advice.

COM exe, C++, and MinGW

Have abit of an odd question; I'm using a tool supplied by a large company that, for reasons I find somewhat baffling, uses a COM interface defined inside the exe itself. In the example code they provide, it looks alittle like this.
#import "C:\\Path_To_Exe\\the.exe" rename_namespace ("exe_namespace");
From what I understand, this is the way Microsoft Visual C++ compiler understands the COM and works with it, and I have had the example code working before (currently, it doesn't compile due to fiddling with my build environment).
My question is, is there a way to do the same with MinGW? The project I'm working on is mainly using that; we can use MSVC if required, but I'd ideally like to avoid using multiple compilers if possible. I'm currently using cmake to build with, but I'm willing to use a script to build the items that need the COM interface if needed.
Thanks for your time.
The answer to "is there a way to do the same with MinGW" is no. #import is an optional tool that reads a COM type library (embedded in a binary or not, the TLB corresponds in general to an .idl file, but that also is optional), and generates C/C++ code that's heavily dependent on .c and .h files that only Visual Studio provides.
The answer to "can I do COM with MinGW" is of course yes. I don't know much about MinGW and tools, but you can do COM with any compiler since COM is (just) a binary standard.
If you get rid of #import, you'll have to change the code that uses what was generated (in the .TLH file resulting of the #import directive), COM helper, wrappers, etc. It can be a lot of work, but it's technically possible.
Now, in your context, I suppose it really depends how big the .exe's type library (the description of your COM classes, interfaces, etc.) is. Visual Studio's #import adds value, so you'll have to assess how much value it added for you.
If it's just one class, one interface for example, then it can be interesting to get rid of the #import. If the .exe already has .h files that correspond to the tlb, then you can use them, otherwise you'll have to redeclare some by yourself (and again, change the code that was using generated wrappers).
The sole fact that you ask the question makes me wonder if you have enough knowledge of COM (no offense :-) to get rid of Visual Studio.
The COM subsystem is part of the Windows API, and you can access it using C calls to that API.
However there is a huge amount of boilerplate involved in this. The compilers which support COM "out of the box" have written all this boilerplate, and packaged it up in some combination of compiled libraries, template headers, and so on.
Another part of the usual suite of tools offered by these compilers is one that can read COM interface definitions out of an existing compiled object. COM objects usually contain a binary representation of their interface, for this reason.
There are a few ways you could proceed here in order to use g++; one option is following this broad outline:
Use your MSVC installation to read the COM object and produce a C header file describing the interface.
Pick out the enumerations and GUIDs from that header file.
In g++, use the Windows API to invoke the object, using those enumerations and GUIDs.
If you want to author objects in g++ then there is a lot more work to do as you need to implement a bunch of things, but it is possible.
I have done this successfully in the past with g++ (as part of testing COM objects I'd developed). Probably somebody could develop a nice open-source suite for using COM objects, or even for authoring, that does not depend on MSVC but I'm not aware of such a thing.
I would recommend reading the books by Don Box, they fill in a lot of gaps in understanding that you will have if you've only learned about COM by working with it and reading the internet.

Libraries vs classes in c++

I came across a terminology in C++ which is a library. The book I am reading states that iostream is a library , and it is a system library. Then After that it says in the book, "later, you will create your own library with the extension .h". Is a library the same as class because clearly, when I included my .h library, I actually had created a class.
If a library is the same as a class, what can we say about in C language , is it a class ?
Thank you.
Please note that this is just a simplistic explanation so you can wrap your head around it, not a pedantic or an exact and complete definition of a library.
A library is a collection of functions, classes and other stuff packaged together.
For instance the C++ standard library is (conceptually) composed of many libraries, e.g.:
string library
algorithm library
input/output library
etc.
The IO library contains some classes like:
std::iostream (actually a typedef to std::basic_iostream)
std::ios
std::istream
std::ostream
etc.
In order to use a library you basically need two things: the library headers in order to have access to the declarations and a library which needs to be linked to your project in order to have access to the symbols exported by such library. The OS comes with the C++ Standard Library preinstalled and the compiler -- when in C++ mode -- automatically links to it, so all you have to do is include the necessary headers.
In order to understand what a header is and what's it's role you first need to understand the difference between declaration and definition. You can reefer to What is the difference between a definition and a declaration? or any other reading material.
Then you need to understand the concept of compilation units. You can read What is a “translation unit” in C++ or How is compilation unit defined in c++.
Using all the above you should to be able to compile multiple source files into one executable and understand the basics mechanism involved. You can read Using multiple .cpp files in c++ program or How to use multiple source files to create a single object file with gcc
From here there is a small step to be able to create and use your own static library. You can start here: How to create a static library with g++?
Another important concept to understand is compilation/linking: How does the compilation/linking process work?
...or alternatively all you need to know is that in order to use std::iostream you need to include <iostream>. Ultimately it's up to you how much you want to absorb as "because that's how it's done" and how much you want to understand. Progress can be made only if you chose one of the options (spoiler: it's the latter).

parser generator that generates stand-alone C++ code

Is there a LALR parser generator that produces stand-alone C++ code? I am hoping that it would generate two files named something like "Parser.cpp" and "Parser.hpp," and the generated parser is implemented in a single class (that I can wrap in whatever namespace) that I can use for my parsing needs.
I want to use it for fun (i.e. small personal projects), and I'd like the output to be stand-alone (without any headers) so that I know I can compile it wherever I have a C++ compiler.
The search so far:
I've looked at flex/bison, but AFAIK they both require special headers and libraries. I've also looked at ANTLR a little bit, but it is not obvious to me that it can generate stand-alone C++ code. If someone can confirm that it can, then I might look more into it.
GOLD Parser (Bart Kiers mentioned the list on Wikipedia) has support for C and C++ languages. It does not generate a completely self-contained C/C++ source code file. All it does is the generation of Lexer/Parser tables which can be consumed by the "parsing engine".
To accomplish your task (or something similar) I did the following:
Prepare your LALR grammar in Gold's format
Generate parsing tables (one binary file)
Use an old trick to convert the binary file into a header file like
unsigned char ParseTable[] = { ... };
Modify the loader from the "parsing engine" sources (or use the C version which supports in-memory loading, as I remember)
Combine the sources for the GPEngine (if it is a C++ version) into the .h/.cpp pair.
Append the ParseTable to .cpp
Sure, it's not that straightforward, but all the steps can in principle be done within a single "combine" script which can be used with a number of grammars.
I guess the major drawback is the fact that GOLD is closed-source and windows-only (it means that to produce the parsing tables you have to use Windows machine).
ANTLR can generate C++ code although IMHO I find the support for C++ is a bit weak, it is more like C code. Still it is a good environment to work with ANTLRWorks giving you a graphical representation of your syntax tree.
The output from flex+bison consists of two .c files and one .h file. These are completely stand-alone, in that they are all you need to compile into your application to make use of the parser. There are no additional libraries or headers needed (beside the standard C ones).
Unless I've misunderstood your requirements, you definitely can do what you want with flex+bison.

Map existing C++ function to JNI

I have a library that I am compiling and creating a fully standalone C++ program. There are two cpp files, one that has the main, the other with all the functionality.
Currently, this program is implemented with a Java ProcessBuilder with args to call the C++ program and the results of that C++ program just simply go out to a file.
Now, I am wanting to get the results of that C++ function that does that work back to my java program. (The results in the C++ function is a double unsigned char array)
So my question is - is there a way to map those existing library functions so that I can call them from my java program directly, AND still keep using that library in the stand-alone way that I currently am, which is through that driver C++ program main()?
I am basically trying to avoid having to compile the same library twice - once for JNI functionality, and once as a standalone C++ program
Thanks
Java Native Access (JNA) will do what you want.
Java Native Interface (JNI) requires an additional layer of C glue between Java and C++. But JNA can access some C functions directly from Java.
You'll probably need to declare your function extern "C". You won't have to recompile the library, but you will have to link it with your C++ main function.
If you had a large C++ class library to expose, then you'd might be interested in SWIG. But for single C function, JNA is probably sufficient.
I think an exe can export functions similar to a dll (using __declspec(dllexport) on windows), which means you might be able to load it similarly to a jni-dll. (You might need to rename it .dll or .so to have java load it though.)
If loading doesn't work, another way would be to start your program in a separate process as you do now, but give it an command-line option which establishes some kind of shared-memory-area with the Java program.
That would avoid copying the daya back and forth, but might require a small utility DLL loaded by both the exe and the java program, i.e. not simpler. (Not sure if Java can setup shared-memory easily w/o native c calls ..)
(keeping answers separate for voting/comments/accept granularity)
Create a JNI wrapper DLL that runs the executable and returns the chars. Alternatively, compile the relevant code into a static library and link it either to a main() function for a standalone program, or to a JNI stub for calling from Java. In-process always better.
I believe a proper way to do it would be first to compile your functions into an independent dynamic library (.dll / .so / .dylib).
Then you can :
write a C++ executable that links against your shared library
write a Java program that binds to your C++ library thanks to BridJ, for instance (or JNA, if you stick to plain old C)