'Retrieving a stack-allocated value from a C++/CXX.rs-managed binding

I am calling out to a C++ library from inside of Rust. I am using the CXX binding generator along with some C++ "glue" code. The idea is that I initialize an object (easy enough) and then call a method to get an "enumerator" data type. It doesn't matter that it's an enumerator but it is important to note the enumerator is passed back as a stack-allocated piece of data.

The C++ library has this signature:

TautomerEnumeratorResult RDKit::MolStandardize::TautomerEnumerator::enumerate   (   const ROMol &   mol )   const

So you create a TautomerEnumerator instance, pass in a Mol reference, and the method gives you a stack TautomerEnumeratorResult.

The C++ wrapper side of the CXX bridge looks like:

#include "rust/cxx.h"
#include "GraphMol/GraphMol.h"
#include "GraphMol/SmilesParse/SmilesParse.h"
#include "GraphMol/SmilesParse/SmilesWrite.h"
#include "DataStructs/ExplicitBitVect.h"
#include "GraphMol/Fingerprints/Fingerprints.h"
#include "GraphMol/MolStandardize/Tautomer.h"

namespace RDKit {
    using ExplicitBitVect = ::ExplicitBitVect;
    using TautomerEnumerator = MolStandardize::TautomerEnumerator;
    using TautomerEnumeratorResult = MolStandardize::TautomerEnumeratorResult;

    TautomerEnumeratorResult enumerate_tautomer(TautomerEnumerator *enumerator, std::shared_ptr<ROMol> mol) {
        return enumerator->enumerate(*mol);
    }
}

which is fine. the Rust side of the CXX bridge looks like:

#[cxx::bridge(namespace = "RDKit")]
pub mod ffi {
    unsafe extern "C++" {
        include!("wrapper/include/rdmol.h");

        pub type TautomerEnumerator;
        pub type TautomerEnumeratorResult;
        pub unsafe fn tautomer_enumerator() -> *mut TautomerEnumerator;
        pub unsafe fn enumerate_tautomer(mol: SharedPtr<ROMol>) -> TautomerEnumeratorResult;
    }
}

which blows at compile time with:

  error[cxxbridge]: returning opaque C++ type by value is not supported
    ┌─ src/cxx/bridge/mol_standardize.rs:9:68
    │
  9 │         pub unsafe fn enumerate_tautomer(mol: SharedPtr<ROMol>) -> TautomerEnumeratorResult;
    │                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^ returning opaque C++ type by value is not supported
    │
    = hint: wrap it in a UniquePtr<> or SharedPtr<>

But since it's a stack allocated variable I can't return it. Is there a zero cost way of sharing TautomerEnumeratorResult with Rust over the stack? How can I make the variable "non opaque" when it's a class and not a struct?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source