Public API:

// rust/cxx.h

#include <iosfwd>
#include <string>

namespace rust {

class Str final {
  Str() noexcept;
  Str(const Str &) noexcept;
  Str(const String &) noexcept;

  // Throws std::invalid_argument if not utf-8.
  Str(const std::string &);
  Str(const char *);
  Str(const char *, size_t);

  Str &operator=(const Str &) noexcept;

  explicit operator std::string() const;

  // Note: no null terminator.
  const char *data() const noexcept;
  size_t size() const noexcept;
  size_t length() const noexcept;
  bool empty() const noexcept;

  using iterator = const char *;
  using const_iterator = const char *;
  const_iterator begin() const noexcept;
  const_iterator end() const noexcept;
  const_iterator cbegin() const noexcept;
  const_iterator cend() const noexcept;

  bool operator==(const Str &) const noexcept;
  bool operator!=(const Str &) const noexcept;
  bool operator<(const Str &) const noexcept;
  bool operator<=(const Str &) const noexcept;
  bool operator>(const Str &) const noexcept;
  bool operator>=(const Str &) const noexcept;

  void swap(Str &) noexcept;

std::ostream &operator<<(std::ostream &, const Str &);

} // namespace rust


Be aware that rust::Str behaves like &str i.e. it is a borrow! C++ needs to be mindful of the lifetimes at play.

Just to reiterate: &str is rust::Str. Do not try to write &str as const rust::Str &. A language-level C++ reference is not able to capture the fat pointer nature of &str.


Allowed as function argument or return value. Not supported in shared structs yet. &mut str is not supported yet, but is also extremely obscure so this is fine.


// src/

mod ffi {
    extern "Rust" {
        fn r(greeting: &str);

    unsafe extern "C++" {
        fn c(greeting: &str);

fn r(greeting: &str) {
    println!("{}", greeting);

fn main() {
    ffi::c("hello from Rust");
// include/greeting.h

#pragma once
#include "example/src/"
#include "rust/cxx.h"

void c(rust::Str greeting);
// src/

#include "example/include/greeting.h"
#include <iostream>

void c(rust::Str greeting) {
  std::cout << greeting << std::endl;
  r("hello from C++");