Skip to content

The Smarter Way to Rust

If you’ve been following our blog, you’re likely aware of Rust’s growing presence in embedded systems. While Rust excels in safety-by-design, it’s also common to find it integrated with C++. This strategic approach leverages the strengths of both languages, including extensive C++ capabilities honed over the years in complex embedded systems. Let’s delve into some key concepts for integrating Rust and C++.

Adding Rust to C++

If you’re adding Rust to an existing C++ project, you need to start in the right place. Begin by oxidizing (that is, converting code to Rust) areas that are bug-prone, difficult to maintain, or with security vulnerabilities. These are where Rust can offer immediate improvements. Focus on modules that are self-contained, have clean interfaces, and are primarily procedural rather than object-oriented. For example, libraries that handle media or image processing can be prime candidates for rewriting in Rust as these are often vulnerable to memory safety issues. Parsers and input handling routines also stand to benefit from Rust’s guarantees of safety.

Deciding between Rusting outside-in or inside-out

As your project scales, weigh the merits of maintaining a C++ core with Rust components versus a Rust-centric application with C++ libraries. For smaller, newer projects, starting with Rust may help you avoid the complexities of dealing with C foreign function interfaces (FFIs). This decision may hinge on your safety priorities: if your project’s core tenant is safety, then a Rust-centric approach may be preferable. Conversely, if safety is needed only in certain areas of C++ project, keeping the core in C++ could be more practical.

Another consideration is how your project handles multi-threading. Mixing threading and memory ownership between Rust and C++ is very complex and prone to mistakes. Depending on how your application uses threads, this may tilt the decision in the direction of either C++ or Rust as the main “host” application.

Keeping C++ where it excels

While Rust offers many advantages, particularly in safety, C++ has its own merits that shouldn’t be hastily dismissed. The decision to rewrite should be strategic, based on actual needs rather than a pursuit of language purity since the risk of introducing new bugs through rewriting well-tested and stable C++ code outweigh the benefits of a Rust rewrite. Time-tested C++ code, particularly in areas like signal processing or cryptography, might be best left as is. Such code is often highly optimized, stable, and less prone to memory-related issues. As the saying goes, if it’s not broken, don’t “fix” it.

Navigating Rust limitations

Despite its growing ecosystem, Rust is still relatively young. Relying on packages maintained by small teams or single individuals carries inherent risks. Moreover, as Rust is still in a period of rapid language evolution, this could result in frequent updates, posing challenges for large-scale or long-lived projects. In certain scenarios, such as very large codebases, specific embedded support requirements, or projects with long development cycles, C++ may remain the more practical choice. It is wise to use C++ where stability and longevity are important, and Rust where safety is critical but some development fluidity is acceptable.

Summary

By combining the reliability of C++ with the safety of Rust, developers can engineer systems that endure while minimizing the risk of common programming pitfalls. If you’re interested in reading more about this topic, you’ll want to read our best practice guide on Rust/C++ integration, which was created in collaboration with Ferrous Systems co-founder Florian Gilcher.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

Leave a Reply

Your email address will not be published. Required fields are marked *