Get the latest AI workflows to boost your productivity and business performance, delivered weekly by expert consultants. Enjoy step-by-step guides, weekly Q&A sessions, and full access to our AI workflow archive.
Summary
In this enlightening lightning talk, Yash, a Rust Developer Advocate at Microsoft, explores the exciting possibilities of integrating C++ with Rust. Despite being relatively new to C++, Yash brings considerable expertise from his work with Rust to present three methods of bridging these languages. The talk delves into Rust's creation, characteristics, and why it's rapidly becoming a preferred language for system-level programming. It covers basic Rust syntax, semantics, and demonstrates how Rust offers memory safety without runtime overhead. Yash walks through using C ABI for linking C++ and Rust, employing the bindgen tool, and the advanced cxx library for higher-level type integration. He concludes by highlighting the ongoing improvements and future potential of these tools for seamless interoperability.
Highlights
Bridging C++ and Rust can be achieved using C ABI, bindgen, and the cxx library. 🔗
Rust ensures memory safety at compile time, setting it apart from many other languages. ⏲️
Yash demonstrates Rust's compatibility with high-level features of C++ through practical examples. 💻
Bindgen generates Rust bindings from C++ headers, reducing manual coding effort. 🤖
The cxx library allows the use of high-level strings and smart pointers between Rust and C++. 📚
Key Takeaways
Rust is remarkably compatible with C++, offering memory safety without the overhead. 🛡️
Tools like bindgen and cxx streamline the interoperability between Rust and C++. 🔧
The Rust language promotes safer, concurrent programming through its unique features. 🚀
Microsoft and other big names are actively incorporating Rust, signaling its growing importance. 🌐
Rust's ecosystem is steadily growing, with ongoing tool improvements enhancing user experience. 🌱
Overview
Yash starts off with a primer on Rust, explaining its inception at Mozilla and its focus on providing memory safety with zero runtime overhead. This sets the stage for the central theme: bridging C++ with Rust, primarily for systems programming. Given Rust's system-level prowess, it's a language quickly adopted by major industry players, including Microsoft. Yash aptly emphasizes Rust's compatibility, most notably its ability to integrate smoothly with C++, offering developers robust tools for improving memory safety without sacrificing performance.
The main body of the talk takes attendees through three distinct methods of integrating Rust with C++. The session begins with the foundational approach using C ABI, which, while flexible, demands tedious boilerplate code. Yash then highlights bindgen, a significant leap forward, automating the generation of Rust bindings from C++ headers, thereby streamlining the workflow. Finally, he covers the cxx library, an advanced tool allowing the use of high-level language features such as strings and smart pointers across both languages, greatly enhancing developer productivity and code ergonomics.
Wrapping up, Yash discusses the ongoing development of these tools and the promise they hold for simplifying multi-language integration. He mentions upcoming projects like Google's Auto cxx, which aims to further bridge functionality with minimal repetition. With a focus on future upgrades and the broadening adoption of Rust, the talk closes on an optimistic note about the evolving landscape of systems programming, encouraging developers to dive into these resources and experiment with the examples provided on GitHub.
Chapters
00:00 - 00:30: Introduction to Bridging C++ and Rust In the introduction to the talk "Bridging C++ and Rust," Yash, a Rust Developer Advocate at Microsoft, sets the stage for discussing three ways to bridge C++ and Rust. Despite being new to C++, having just a week's experience, Yash aims to share insights and techniques for integrating these two languages.
00:30 - 01:00: About the Speaker and Purpose of the Talk The speaker introduces themselves as an expert in Rust, having worked with it for over five years, and they are also involved in its development. While they may not be as experienced with C++, they emphasize the importance of making Rust and C++ work together. The talk will briefly explore what Rust is, its purpose, basic syntax and semantics, and then discuss how to bridge C++ and Rust. The speaker assumes the audience has a familiarity with C++.
01:00 - 01:30: Background on Rust Rust is nearly 20 years old but has only been stable since 2018, making it relatively new compared to C++ and C. It was developed at Mozilla Research to enhance parallelism in the Firefox browser.
01:30 - 02:00: Rust's Features and Ecosystem Fit The chapter titled 'Rust's Features and Ecosystem Fit' discusses the characteristics and design choices of the Rust programming language. Rust is portrayed as a language with a sophisticated type system similar to Haskell or OCaml, specifically pointing out its use of a Hindley-Milner type system, which emphasizes type safety. Unlike Haskell and OCaml, Rust adopts a C-like syntax, making it accessible to those familiar with languages like Java, JavaScript, and C. The decision to create a programming language like Rust was driven by the need to solve complex problems, implying Rust's capability to tackle such challenges.
02:00 - 02:30: Syntax and Semantics of Rust This chapter discusses the syntax and semantics of the Rust programming language, emphasizing its memory safety features. Rust provides memory safety with no runtime overhead by checking memory moves, borrows, and landings during compile time. This results in code that runs as fast as C or C++. Additionally, Rust offers native C interoperability, allowing for the gradual replacement of C components.
02:30 - 03:00: Hands-on Example: Manual C++ and Rust Binding The chapter discusses how Rust, as a modern systems programming language, can be integrated with existing C codebases. It highlights Rust's ability to interface with C, offering improvements in memory safety and bug prevention, which is particularly beneficial for maintaining or replacing old, critical C code. The strength of Rust lies in its compatibility with current ecosystems, allowing for enhancements without a complete rewrite. Additionally, it mentions Rust's support for modern asynchronous I/O operations.
03:00 - 03:30: Intermediate Level: Using Bindgen The chapter discusses the usage and advantages of Bindgen, particularly focusing on its role in facilitating parallelism and concurrent systems in programming. The async/await notation in Bindgen makes it easier to manage parallel tasks and helps prevent data races, which is crucial for multi-threading.On the application side, Rust, the programming language Bindgen is associated with, is being widely adopted by key industry players like Microsoft, AWS, Cloudflare, and even operating system kernels. Notably, Windows 11 Insider builds have started incorporating Rust within their kernel.
03:30 - 04:00: Advanced Level: Using cxx Library This chapter explores the advanced usage of the CXX library, which is becoming prevalent in various systems including Linux and Android due to its performance and safety benefits. Particularly, in Android, components like the Bluetooth stack have been re-implemented in Rust to enhance these aspects. Additionally, the chapter provides an overview of Rust programming, offering a cheat sheet for syntax including the use of 'fn' for functions and return type arrows.
04:00 - 04:30: Additional Tools and Options The chapter titled 'Additional Tools and Options' discusses the syntax and semantics related to Rust programming, particularly focusing on declarations and methods on structures using 'impul blocks'. It notes the comparison with how TypeScript handles names and types. The chapter emphasizes that, in Rust, all values utilize move semantics similar to those in C++. However, the discussion also notes the absence of support for move constructors in the current context.
04:30 - 05:00: Conclusion and Further Resources The chapter discusses the concepts of unique and shared references in Rust programming. Unique references can be mutated, whereas shared references are read-only. A key point is that you cannot use a unique and a shared reference simultaneously; you must opt for one. This is enforced by the compiler, contributing to Rust's memory safety without runtime performance penalties. The text hints at Rust struct definition but doesn't elaborate.
Bridging C++ and Rust Transcription
00:00 - 00:30 hey everyone welcome to my lightning talk bridging C plus plus and rust my name is Yash um I work as a rest developer Advocate at Microsoft um and today I'll be walking you through three different ways of Bridging the rust and C plus plus languages um just as a heads up I am very much a Sleepless novice I have been programming C plus plus for about a week now um so forgive me if anything's unergonomic unclear not the best uh I haven't been doing this for very long my
00:30 - 01:00 expertise is more uh rust which I have been doing for half a decade now longer um I'm also involved in the development of rust so that that's where my strengths lie um C plus plus not so much but still it's important to make the two work together so let's dive in all right so in this talk we'll briefly cover what rust is why it is then cover some of the syntax and semantics and then talk about bridging C plus plus and rust I will be assuming you're familiar here with C
01:00 - 01:30 plus plus but maybe less so with rust so Russ is at this point nearly 20 years old um but it's only been stable for since 2018 which makes it about eight years now so it's it's a pretty recent language about 10 years or 20 years younger than C plus plus and 30 or so years younger than c um it was incubated at Mozilla research in order to help make the Firefox browser parallel because they were trying to do that and it turned out to
01:30 - 02:00 be very difficult um and they decided a programming language might be a good solution for that so rust in a nutshell is a programming language with a very high level type system similar to Haskell or ocamel it's a henley Milner type system which means that pipe safety is is a big thing but unlike ocam on Haskell it uses a c like interface so C like syntax which you know if you've written Java JavaScript C
02:00 - 02:30 C plus plus Etc it should be a lot more familiar to you it's sort of Hallmark feature is it provides memory safety without runtime overhead so it checks uh memory like moves and borrows and landings and all these things completely at compile time and it compiles it away and it leaves you with code that is as fast SC or C plus plus um it also has native C interop so you can piecemeal replace components that
02:30 - 03:00 have been written in C today that may be difficult for numerous reasons say memory sensitive or a safety safety critical sensitive to bugs perhaps very old you know all these things uh rust can help you with and you can replace it you can interop it that's one of its strengths so it doesn't try and reinvent the entire world instead it fits into the existing ecosystems and and systems that people build it also has a very modern like async IO
03:00 - 03:30 facilities it has async await notation um this is the the thing that I help work with so it makes parallelism easy it makes concurrent systems easy to write and it prevents data races uh which which is great when you're dealing with multi-threading um so who's using rust many places including us here at Microsoft but also it's being used all throughout AWS cloudflare uh evening kernels uh since this week it is in the windows 11 Insider build uh inside of the kernel
03:30 - 04:00 but it's also being introduced inside of Linux I believe Android has components such as their Bluetooth stack which they have uh Rewritten and rest um for its its performance and safety safety aspects so that's it for what rust is now let's take a look at rust itself um here's a little cheat sheet for syntax we use the FN keyword for functions we use a little little arrow to return types A Name colon type
04:00 - 04:30 notation for for names and types uh kind of like um I believe typescript does it this way and then you can declare um methods on struct using impul blocks um that's that's the syntax um the semantics are maybe a bit more interesting here where by default all rust values are by move which is move semantics and C plus although we don't support move Constructors but that's a whole thing
04:30 - 05:00 um and we we have uh two types of references as well which is uh unique and shared references um unique reference can be mutated a shared reference can only be read and you can only either have a single unique reference or multiple shared references but but never both at the same time and this is compile time and force and this is what allows rust to be Memory safe um with without runtime overhead so here here's the way you define a struct and rust which is a struct with a name and
05:00 - 05:30 then members inside of it so key like name type pairs um here's how you define functions in rusts in this case uh it returns a zero size unit type rust is also entirely expression based so you know it evaluates the unit expression here um and this this just prints me out to standard out and then here's how you implement methods first we have a getter for the the type name which takes self by reference it's a shared reference and
05:30 - 06:00 returns a string slice and then we have a Setter which takes a new string and that mute itself so you can see that the cell parameter we're just like C plus plus is this but inside of the argument list it says hey we need a mutable reference to self because we're going to update value here okay so to dive into binding C plus plus and rust entirely by hand the the first one
06:00 - 06:30 is we're gonna uh take rust and C plus plus make them both talk uh c a b i to each other and then link them together and that just works that is maximally flexible but it is kind of inconvenient because both rust and C plus plus we like are smart pointers we like our abstractions and if you're going to see ABI um you don't get access to all of that so you you need to oftentimes wrap it in code which is a bit difficult but you know it works and that is pretty great
06:30 - 07:00 so let's take a look at that here we have our cats HPP file which is a struct cat it has a name and it has a bowl whether it's hungry or not then we can construct our cat we can get the cat name we can feed our cat and we can make our cat meow now here's the implementation uh if our cat has not been fed it will meow I'm hungry and if it has been fed it will meow I'm sleepy so yep then on the Rough Side of this that was
07:00 - 07:30 our C plus plus code on Rough Side of this we'll be reusing this example everywhere so you know we just go through it like once um on on the Rough Side of this we have a bill arrest file which is like a make file but native to the rust tool chain um where we invoke the the cmake file uh or this sorry the cmake library to to use cmake to build the the C plus code then we say hey please build the C plus code and it builds it and then I haven't printed the
07:30 - 08:00 invocations here but there's ways of saying like Okay and then please also link it as part of the build um the full example which I'll link at the end includes all of this so you can like go through and browse it yourself then the rust code itself it redeclares the same struct it says hey this struct is not rep or rust it is wrapper C so please use C ABI and then we create ffi bindings for all of the methods inside of an extern C block um and that gives us access and then we
08:00 - 08:30 can invoke this using all of this which is just C methods and raw pointers these are not compiler checked by the way so unsafe blocks mean uh you're on the hook for validating that the semantics hold but you still need to uphold the exact same rust semantics you don't get to not uphold them it's just sometimes you you like with ffi the compiler cannot check it for you so you have to check it yourself this is pretty rare it's only at the ffi boundaries and
08:30 - 09:00 for some Primitives that this needs to be done um but yeah here we're doing ffi stuff so uh we take our cat we create our cat and then we call meow then we call feed and we go meow again and that just works um okay intermediate level rather than needing to like we saw here uh redeclare destruct and also here you know earlier have the multiple definitions um what we can do instead is use a tool called bindgen which will read the
09:00 - 09:30 header files from C plus plus and auto generate rust bindings we can then use that to call things and it will just be less work so here is again our cats.hp file in this case we no longer need to use struct because we're not using extern C anymore we are just using negative C plus plus classes so here's our class with all the methods like earlier but in class form and then we create the implementation
09:30 - 10:00 there still same logic but then in the rust build file we do something different namely we call it bindgen tool to generate our bindings and then we build a c plus code and then it gets Linked In the bindings get generated and then in our main file we can take those bindings and just use those so rather than doing the free functions like we saw earlier we can now see that our cat has methods on it so we can call meow and cat.feed
10:00 - 10:30 which is a lot more convenient so buying chain is great when you can use it I highly recommend using it there's also the inverse tool called C by engine if you want to create rust take rust and like create C binding C headers for it um yes okay so for the final example what if we wanted to go like all the way through so far we've been seeing uh things like Carstar Char star strings but rust and C plus plus both have access to Native strings like high level string
10:30 - 11:00 representations which are nicer to use other types such as smart pointers and the cxx library allows you to to create a bridge between the two using these high level types so it is aware of rest and C plus plus libraries and it makes sure that those like like ergonomic you can create ergonomic like bridging between the two so uh in this example what we'll be doing is we'll be round tripping so we created definition and rest call that from C plus plus
11:00 - 11:30 and then export a function again from uh to rust which we then invoke so our header now is just the void function test we just gave it a something name doesn't matter because this is what we'll be using from Russ then in our implementation tests calls or rust types here we say hey please uh create a cat and then call meow and feed again unfortunately cxx is not yet aware of how Constructors work so this is a free
11:30 - 12:00 function to create our our struct or a class um but then from there it's it's you know the methods do work in order to build it what we can do is we can use the cxx build um Library we can give it some flags and that just works now on the right side rather than defining the the types on the C side or sorry on the C plus plus side um we're now doing it on the rough side and we say hey extern rust within this
12:00 - 12:30 like cxx Bridge construction we say hey here's an extern rust block with all the methods and a shared struct named cat with um a name and is hungry and then importing from C plus plus we say hey there's a function called test that we would like to have access to and then the actual implementation so those were the headers the actual implementation here is like we have neocat which implements all logic and it's it's pretty much the same logic rest in C plus plus look look pretty
12:30 - 13:00 similar in in many cases um so yeah the the only thing that probably stands out here is that fee takes a mutable reference to self because it mutates it updates that is hunger field everything else takes a shared reference and then here we call ffi test which invokes the C plus plus code and that works um okay just the the final bits here um there are more options that you can investigate if you're interested uh cxx can be combined with buying gen to make
13:00 - 13:30 things more convenient unfortunately uh ran out of time to try it as well as I said they've only been doing this for a week um the Google auto cxx project which is an unofficial project um takes both libraries and is intended to make that more convenient I have also not tried it but I I really like the premise of that because I've found myself needing when using cxx which is what you would want to be using if you could um there's some repetition involved but
13:30 - 14:00 Auto cxx removes that repetition which seems very promising there's also cxx async which adds support for async types and finally C by engine as mentioned earlier if you want to create um like wrap rust code into like uh C headers and make that like automate that project um yes so in conclusion rust is a memory safe programming language it has native interrupt with c and with with some use of tooling you can also make it
14:00 - 14:30 interrupt with C plus those tools are being actively developed and they're improving um all the time so hopefully this will become easier over time and I'm very excited for where this is going I hope this was useful um if you're interested in seeing these examples trying them out building them yourself you can go to this URL on GitHub where you can find all three examples checked in and my slides as well so you can read those over if you want to thank you so much