Skip to content

paandahl/cpp-with-rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minimal application mixing C++ and Rust

This example uses cxx to generate bindings between C++ and Rust, and integrates the two parts through CMake.

It is basically an inverted version of cxx's demo code, using C++ for the entry point and a MultiBuf class, while implementing a simple blobstore-library in Rust.

How it works

In lib.rs we add bridge declarations for our Rust types:

#[cxx::bridge(namespace = "org::blobstore")]
mod ffi {
    // Rust types and signatures exposed to C++.
    extern "Rust" {
        type BlobstoreClient;
        fn new_blobstore_client() -> Box<BlobstoreClient>;
        fn put(&mut self, parts: Pin<&mut MultiBuf>) -> u64;
        ...
    }
}

fn new_blobstore_client() -> Box<BlobstoreClient> {
    Box::new(BlobstoreClient { blobs: HashMap::new() })
}

struct BlobstoreClient {
    blobs: HashMap<u64, Blob>,
}

impl BlobstoreClient {
    fn put(&mut self, mut parts: Pin<&mut MultiBuf>) -> u64 {
        ...
    }
}

In build.rs we add logic to generate C++ bridging code from the declarations:

fn main() {
    cxx_build::bridge("src/lib.rs");
    println!("cargo:rerun-if-changed=src/lib.rs");
}

In CMakeLists.txt we add a custom command to trigger the Rust build:

add_custom_command(
        OUTPUT ${BLOBSTORE_BRIDGE_CPP} ${BLOBSTORE_LIB}
        COMMAND cargo build --manifest-path ${BLOBSTORE_CARGO_MANIFEST}
        ...
)

In main.cpp we include the generated C++ header, construct Rust types, and call their methods:

#include "lib.rs.h"

int main() {
    auto client = org::blobstore::new_blobstore_client();
    ...
    const auto blobid = client->put(buf);
}

The application also consumes C++ types from Rust (MultiBuf), and leverages shared types between the two languages (BlobMetadata).

To learn more about the bridging layer, check out cxx's documentation.

Building and running the code

  git clone git@github.com:paandahl/cpp-with-rust.git
  mkdir cpp-with-rust/build
  cd cpp-with-rust/build

  cmake ..
  cmake --build .
  ./cpp_with_rust

NOTE: If you are using Windows, run these commands in the Developer PowerShell for VS.

Technical notes

  • As opposed to the original cxx demo, build.rs only generates the C++ bridging code, without compiling it. Instead, we pass it in to the CMake build by referencing it in add_executable().
  • For simplicity, this example always builds the Rust code in debug mode. See here for suggested changes to adhere to the specified CMAKE_BUILD_TYPE, and moving the cargo output to within the CMake build tree.

License

The code is available under the MIT license.