7

I wrote a test program to check that the data will be read correctly on the Rust.

C++ code:

std::vector<float> vec;
vec.push_back(10);
vec.push_back(20);
std::cout << "len is " << get_len(&vec);

Rust code:

#[no_mangle]
pub extern "C" fn get_len(vec: *const Vec<f32>) -> i32 {
    let vec= unsafe { &*vec};
    vec.len() as i32
}

My output looks like this and is always different:

len is 603268424
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 9
    C++'s `std::vector` has no guarantees on layout (it's very likely to be different across standard library implementations). You need to reduce it to something that both languages can understand, possibly something like passing `vec.data()` and `vec.size()` separately. – milleniumbug Jun 06 '19 at 16:58

1 Answers1

11

One thing to know is that C++ doesn't allow giving away the ownership of the data vector. This is a limitation of the C++ design. There are some tricks but I don't advise using them. To stay "safe", you can only borrow a C++ vector.

This can be done easily, using vector::data() and vector::size():

#include <cstddef>
#include <vector>

extern "C" void show_vector(float const *data, std::size_t size);

int main() {
    std::vector<float> vec{10, 20};
    show_vector(vec.data(), vec.size());
}

The Rust side can use slice::from_raw_parts(), creating a view of our vector without taking ownership.

use libc::{c_float, size_t};

extern "C" fn show_vector(data: *const c_float, size: size_t) {
    let vec = unsafe { std::slice::from_raw_parts(data, size) };
    for x in vec {
        println!("{}", x);
    }
}

Read more:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • Thank you! Great answer! Also working with `std::vector` -> `Vec`! Very helpful! – Artem Kolokoltsev Jun 07 '19 at 09:12
  • @ArtemKolokoltsev Be sure to at least use [`#[repr(C)]`](https://doc.rust-lang.org/nomicon/other-reprs.html#reprc) on Rust side, it's not perfect but better than nothing, be aware that you could run into problem if you are not extra careful with data representation. "We strongly recommend using rust-bindgen and/or cbindgen to manage your FFI boundaries for you." – Stargateur Jun 07 '19 at 09:20