[HN Gopher] CXX - safe interop between Rust and C++
       ___________________________________________________________________
        
       CXX - safe interop between Rust and C++
        
       Author : synergy20
       Score  : 245 points
       Date   : 2022-03-10 14:47 UTC (8 hours ago)
        
 (HTM) web link (cxx.rs)
 (TXT) w3m dump (cxx.rs)
        
       | talal7860 wrote:
        
       | rvz wrote:
       | I'm not sure how this can scale since it is still not automatic
       | and requires tweaking and maintenance of the bindings; or even if
       | the library has a new update. (As there can be new errors, bugs
       | generated from those bindings)
       | 
       | It still would be painful to maintain and update your Rust
       | project and cargo configs with your C++ code alongside a third
       | party crate maintained by one person in the project. D Lang is
       | probably the only language that has this built into into the
       | language and is done automatically.
       | 
       | I'd still rather go for a first party library with this support
       | or C++ interop support feature built into the language like D
       | with the whole requirement of it being completely automatic.
        
         | gavinray wrote:
         | Surprisingly, Swift can do C++ direct interop too, without
         | writing any mappings/type definitions:
         | 
         | https://forums.swift.org/t/swift-and-c-interoperability-work...
         | 
         | https://github.com/apple/swift/blob/main/docs/CppInteroperab...
         | 
         | https://github.com/apple/swift/blob/main/docs/CppInteroperab...
        
           | worik wrote:
           | If you are in the unfortunate position of having to use
           | swift....
        
         | pcwalton wrote:
         | autocxx is a companion library that provides what you're
         | looking for. https://github.com/google/autocxx
        
           | dureuill wrote:
           | That _attempts_ to provide it. I have been trying to use
           | autocxx for a while, without success at the moment.
           | 
           | It is very actively developed though so I trust that we'll
           | get there eventually.
        
         | aaron_m04 wrote:
         | I was under the impression that both .cpp and .cc were far more
         | common.
        
           | cylon13 wrote:
           | You may have replied to the wrong comment thread
        
         | couchand wrote:
         | FFI is painful, to be sure. Making sure the bindings you say
         | you're using match the ones you're actually using is tedious
         | and error-prone.
         | 
         | Which is where CXX comes in: the static analysis tells you if
         | you're holding it wrong. So to your first point, the compiler
         | will tell you exactly what needs to change.
         | 
         | I don't know what the developer experience with D/C++ interop
         | looks like, but unless I'm missing something big I'd assume
         | you'd still need to make changes when the library has updates.
        
         | girvo wrote:
         | It's also built into Nim, for what it's worth, though I do
         | think D's handling of C++ is more ergonomic.
        
       | rajman187 wrote:
       | I used this as an intermediate step for getting a small rust
       | geospatial library working with Google S2 Sphere, which is
       | written in C++, until the Rust implementation is ready. It works
       | flawlessly. David Tolnay (https://github.com/dtolnay) is great
        
       | bee_rider wrote:
       | It seems unfortunate that they decided to stylize this as CXX
       | (all caps). CXX is already in use nearby as the conventional
       | stand-in for the c++ compiler in (for example) makefiles, and the
       | library itself seems to be called cxx (lower case) in their
       | example code.
        
         | LordDragonfang wrote:
         | Should have been CO2 (An oxidized C)
        
           | bee_rider wrote:
           | Dang it, where were you when they named this thing, that's
           | perfect.
        
       | WalterBright wrote:
       | D does this as:                   extern (C++) int foo(long x);
       | 
       | and takes care of the C++ name mangling and function call ABI for
       | your. It works for structs, inheritance, COM classes, member
       | functions, namespaces, typedefs, even templates.
        
       | rajman187 wrote:
       | Worth sharing also is the async implementation that works with
       | C++20 coroutines https://github.com/pcwalton/cxx-async
        
       | KptMarchewa wrote:
       | IMO PyO3 project is more useful. C++ and Rust cover similar
       | field, while Python and Rust are good at so vastly different
       | things that they complement each other much more.
        
         | kmeisthax wrote:
         | The purpose of C++/Rust bridging is to allow adding Rust code
         | to existing C++ projects. PyO3 lets you embed a Python
         | interpreter in an otherwise Rust-only application. They serve
         | two different markets - though, if you really needed to, you
         | could embed both C++ libraries and CPython in the same Rust
         | app.
        
         | pcwalton wrote:
         | Both cxx and pyo3 are useful, and there's no need for them to
         | compete. cxx is used in production at massive scale.
        
       | netr0ute wrote:
       | What's the point of using C++ in Rust when you could use Rust
       | instead and not have to add a cargo package?
        
         | mcronce wrote:
         | It takes a lot less time than rewriting [component] in Rust
        
         | detaro wrote:
         | Rewriting a few million lines of existing C++ is not cheap nor
         | quickly done.
        
         | codetrotter wrote:
         | I have a pretty cool use case where I successfully interfaced
         | between C++ and Rust code.
         | 
         | This was for a project consisting of a sculpture with a bunch
         | of LED strips on it, and my part was to do the programming,
         | electronics and wiring for it.
         | 
         | To control the LED strips I use Teensy 3.2 microcontroller
         | boards, with the OctoWS2811 adaptor board [0], along with an
         | industrial singleboard computer.
         | 
         | The Teensy 3.2 boards I programmed using the Arduino libraries
         | and the OctoWS2811 library [1]. The code I wrote for this part
         | was C++. (But I don't use the Arduino IDE, I use JetBrains
         | CLion.)
         | 
         | Compiling and flashing the firmware for the Teensy, and
         | disconnecting and reconnecting cables etc was making the
         | development a bit annoying.
         | 
         | So in Rust I wrote a LED simulator program that renders the
         | "pixels" of the LED strips on my screen, and I compiled my C++
         | code that I've written for the microcontrollers on the host,
         | with some shims that I wrote to provide some functions that my
         | firmware uses, and I link this with my Rust program.
         | 
         | The end result is that I have a fully functioning LED simulator
         | that I use while developing, that runs on my computer. It runs
         | on both macOS and Linux. And then the same C++ code of mine
         | gets included and built without modification when I build my
         | firmware for the microcontrollers.
         | 
         | It is work that I am very satisfied about :)
         | 
         | Should also note that I use the bindgen crate, not cxx.
         | https://crates.io/crates/bindgen
         | 
         | [0]: https://www.pjrc.com/store/octo28_adaptor.html
         | 
         | [1]: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html
        
           | chris_overseas wrote:
           | This sounds great, I'd been thinking about creating something
           | similar (I also have a project with Teensy 3.2/4.0,
           | OctoWS2811 and CLion). Is there any chance you'd be willing
           | to open source it? In particular I'd be interested in what
           | you did to get the Teensy code compiling and running on the
           | host with the shims you mention.
        
             | girvo wrote:
             | If your board supports it, the Zephyr RTOS and build tools
             | support building your firmware for a Linux binary target
             | too :) even has a neat RPC protocol to test the firmware on
             | your computer rather than on the board.
             | 
             | Probably too much for a Teensy tho, but it is supported:
             | 
             | https://docs.zephyrproject.org/latest/boards/arm/teensy4/do
             | c...
        
         | tux3 wrote:
         | It's not just about using C++ libraries from Rust, but also the
         | other way around.
         | 
         | You have 15 million lines of C++ code, and you want to start
         | writing some components in Rust. At the interface, you need a
         | bridge.
        
         | [deleted]
        
         | [deleted]
        
         | deadcore wrote:
         | If you have existing resources written in C++, external libs,
         | maybe you've created a 'plugin' which is loaded by an
         | application but the plugin is written in Rust and the app is
         | written in C++ and it needs to invoke back into the main
         | applications code. Just examples of stuff where I've had to
         | interop Rust with other things outside of my control :)
        
         | ben-schaaf wrote:
         | There's lots of useful C++ libraries that don't have (good)
         | rust bindings.
        
         | onceiwasthere wrote:
         | I guess if you already have C++ that you'd prefer not to re-
         | write. Also things like graphics programming, while making
         | great strides in rust, are definitely still superior in C++ in
         | certain aspects so you might want to write, say, an OpenGL
         | interface in C++.
        
         | sgeisenh wrote:
         | There is a lot of code written in C++. For a lot of large
         | companies, one of the impediments to migrating from C++ to Rust
         | is the investment required to expose the existing C++
         | interfaces in Rust. There are also many open source libraries
         | written in C++ that you can more easily call from Rust using
         | this bridge library.
        
         | pjmlp wrote:
         | Plenty of ecosystems where C++ rules and no one is going to
         | rewrite any of those libraries.
        
       | sevbo wrote:
        
       | dang wrote:
       | Related:
       | 
       |  _CXX-Qt: Safe Rust bindings for Qt_ -
       | https://news.ycombinator.com/item?id=30525752 - March 2022 (108
       | comments)
       | 
       |  _CXX - Safe interop between Rust and C++_ -
       | https://news.ycombinator.com/item?id=26565444 - March 2021 (32
       | comments)
       | 
       |  _CXX - safe interop between Rust and C++_ -
       | https://news.ycombinator.com/item?id=25126280 - Nov 2020 (1
       | comment)
       | 
       |  _The CXX Debate_ - https://news.ycombinator.com/item?id=24245372
       | - Aug 2020 (4 comments)
        
         | didip wrote:
         | I am curious Dang, do you do this manually or do you have an
         | automated script for digging relevant submissions in the past?
        
           | dang wrote:
           | It's sort of hybrid. Here are some past explanations
           | 
           | https://news.ycombinator.com/item?id=27726982 (July 2021)
           | 
           | https://news.ycombinator.com/item?id=27284079 (May 2021)
           | 
           | https://news.ycombinator.com/item?id=27236708 (May 2021)
           | 
           | https://news.ycombinator.com/item?id=26886074 (April 2021)
           | 
           | https://news.ycombinator.com/item?id=26245003 (Feb 2021)
           | 
           | https://news.ycombinator.com/item?id=26158300 (Feb 2021)
           | 
           | (I made that list using the same software :))
        
             | kupopuffs wrote:
             | What drives you? What's your ~motivation~?
        
               | dang wrote:
               | Not sure what motivation you're asking about. If you mean
               | motivation for posting links to past discussions--it's my
               | job to help HN be as interesting as possible (see https:/
               | /hn.algolia.com/?dateRange=all&page=0&prefix=true&sor...)
               | , and readers seem to find those links interesting.
        
             | tus666 wrote:
             | That is so meta.
        
       | misja111 wrote:
       | I would have liked 'CRust' better
        
         | zabzonk wrote:
         | I agree - .cxx is one of the extensions used to differentiate C
         | and C++ code (not that I would recommend its use) and having
         | the library called this may lead to confusion.
        
           | oaiey wrote:
           | Also there is C++/CX (which is C++ interop with the WinRT
           | runtime on Windows).
        
         | ansible wrote:
         | It was taken quite a while ago:
         | 
         | https://crates.io/crates/crust
         | 
         | Seems to be an actually useful P2P networking library, not name
         | squatted.
        
       | ognarb wrote:
       | I used this on a personal projectto use the Lyon library to draw
       | custom shapes in a qml app. If someone is interested I wrote a
       | blog post about it: https://carlschwan.eu/2021/01/20/efficient-
       | custom-shapes-in-...
        
       | cjg wrote:
       | Given that C is a subset of C++ (meh), can you use this to
       | generate safe bindings for C?
       | 
       | Most C integration recommendations I've seen suggest using
       | bindgen, but that doesn't give safe bindings.
        
         | maxnoe wrote:
         | I guess this relies on reference counting via smart pointers
        
           | pcwalton wrote:
           | cxx doesn't rely on reference counting. If you're using
           | reference counted smart pointers in C++, then cxx can bind to
           | them. But it won't impose the overhead of reference counting
           | if you aren't already using it.
        
         | pornel wrote:
         | Not really. The library internally already uses a C ABI,
         | because that's what both C++ and Rust can agree on, but that
         | ABI is not for consumption from C. The point of this library is
         | to preserve higher-level Rust/C++ features like destructors,
         | generic containers, smart pointers, and other things that C
         | can't express.
        
           | cjg wrote:
           | I meant generating a safe Rust API for existing C code rather
           | than calling an existing Rust API from C.
        
             | dangerbird2 wrote:
             | bindgen[1] already exists to autogenerate a rust API from c
             | headers. It's inherently unsafe because C code is
             | inherently unsafe. In particular, there is no language
             | constructs like destructors or constructors, so you can't
             | naively create a C-based API that can prevent
             | memory/resource leaks and use after free errors. While C++
             | does have the same issues as C with unsafe pointer
             | semantics, it does have constructors, destructors, and
             | other features that map almost perfectly with Rust's RAII-
             | based resource management, making it pretty easy to
             | generate a safe(ish) rust interface. In practice, it's
             | pretty easy to create a safe rust API from a C library: use
             | bindgen to create the low-level unsafe API, then create
             | rust wrappers using the ad-hoc creation and descruction
             | library functions to implement RAII.
             | 
             | [1] https://rust-lang.github.io/rust-bindgen/
        
             | pornel wrote:
             | In that direction it's difficult, because C source code
             | doesn't contain machine-readable information about
             | ownership (who and when can free a pointer), lifetimes, or
             | thread safety. C annotations for aliasing, nullability, and
             | lenghts of arrays (malloced, not VLA) are very basic, and
             | rarely used. Lots of C code isn't even const-correct.
             | 
             | Some of these properties could be deduced by a Sufficiently
             | Smart Compiler, but you'd probably need an A.I. that reads
             | the docs.
        
               | girvo wrote:
               | I'm imagining an interactive tool where it asks those
               | questions of the developer when generating the binding
               | code (c2nim is what I use regularly)
        
         | woodruffw wrote:
         | If we're being pedantic (and pedantry matters for safety!) C
         | hasn't been a subset of C++ for a while: they have different
         | type aliasing rules (well-defined aliases in C can be UB in
         | C++), different direct initialization syntaxes, flexible array
         | members, etc.
        
         | kmeisthax wrote:
         | Probably not, and the reason why bindgen code is marked
         | `unsafe` is because that's the default for _all_ Rust FFI. You
         | can 't automatically examine a set of C function signatures and
         | conclude whether or not they're safe - so it's sound to just
         | treat them all as `unsafe` and have the developer document what
         | their safety requirements are, or provide wrapper functions
         | that enforce safety checks at runtime.
        
         | bluejekyll wrote:
         | The problem is that it's not easy to give safe bindings into C
         | because C's memory model is all unsafe by Rusts definitions.
         | You have to manually inspect the C usage of pointers and such
         | to create the semantics in Rust that make its usage safe.
        
       | steeve wrote:
       | I'm using it and it's really well thought out.
       | 
       | Worth noting also is autocxx [1], which is like bindgen, but
       | generates cxx directives. Very clever too. It even allows owning
       | C++ types on the stack.
       | 
       | 1. https://github.com/google/autocxx
        
         | VWWHFSfQ wrote:
         | Oooh autocxx looks very nice. Thanks for sharing that!
        
       ___________________________________________________________________
       (page generated 2022-03-10 23:00 UTC)