# Pass a Vec from Rust to C

**URL:** <https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184>\
**Category:** help\
**Created:** [May 1, 2021, 6:25am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184 "2021-05-01T06:25:19Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![helix\_tp](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/helix_tp/32/11801_2.png) [@helix\_tp](https://users.rust-lang.org/u/helix_tp)\
**Post date:** [May 1, 2021, 6:25am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/1 "2021-05-01T06:25:20Z")

</div>

For a project, I have to build a library that interfaces with a C program.

I'm thinking about how to do it, I don't have any code to show yet.

The idea is that the Rust library does its job and builds a Vec, it passes it to the C program, which interfaces with it.

I'm not sure how to do this.

Thank you.

```rust
#[repr(C)]
pub struct MyStruct {
    pub value : ::std::os::raw::c_int, 
    ......
}

pub extern "C" fn MakeJob(???) -> ??? {
    
    let my_struct = Vec::new();
    for struct_to_export in .... {
        my_struct.push(struct_to_export);
    }
    // export my_struct to C
    ....
}

```

```nohighlight
???? MakeJob(????); 
typedef struct My_Struct
{
    int value;
    ....
} My_Struct;

void main(void){
    // call to MakeJob from Rust lib
    // 
    My_Struct ??? // Retrieve from Rust
    
}
```

---

<div class="post-metadata">

**Author:** ![jameseb7](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jameseb7/32/13257_2.png) [@jameseb7](https://users.rust-lang.org/u/jameseb7)\
**Post date:** [May 1, 2021, 8:23am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/2 "2021-05-01T08:23:19Z")

</div>

You want to pass a pointer to the `Vec` to C, along with its length. The simplest way to obtain the pointer is probably via [`Vec::into_boxed_slice()`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_boxed_slice) and [`Box::into_raw()`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.into_raw). Note that the C code must not attempt to deallocate the pointer, since it comes from a different allocator. Instead, the pointer should be passed to a Rust function that reconstructs the `Box` using [`Box::from_raw`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.from_raw) and then drops it, to ensure it gets deallocated by Rust's allocator.

---

<div class="post-metadata">

**Author:** ![alice](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/alice/32/9777_2.png) [@alice](https://users.rust-lang.org/u/alice)\
**Post date:** [May 1, 2021, 9:07am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/3 "2021-05-01T09:07:42Z")

</div>

You need to split the vector into its three components with the following methods:

- [`Vec::len()`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.len)
- [`Vec::capacity()`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.capacity)
- [`Vec::as_mut_ptr()`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_ptr)

Once you have done this, you can use [`mem::forget`](https://doc.rust-lang.org/stable/std/mem/fn.forget.html) to destroy the vector without running its destructor. Then you just pass the three components to C, and C will be able to access the nth element via the pointer.

To destroy the vector, the C code must pass it back to Rust. Rust can then destroy it by rebuilding it using [`Vec::from_raw_parts`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts). It is not possible to allocate, reallocate or deallocate the vector with the malloc/realloc/free methods in C. All of that must be done by passing it back to Rust. On the other hand, changing the length in C is perfectly fine as long as it doesn't grow larger than the capacity.

@jameseb7 Be aware that `into_boxed_slice()` can be troublesome. It produces a fat pointer which must be split and put back together properly.

---

<div class="post-metadata">

**Author:** ![jameseb7](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jameseb7/32/13257_2.png) [@jameseb7](https://users.rust-lang.org/u/jameseb7)\
**Post date:** [May 1, 2021, 10:03am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/4 "2021-05-01T10:03:08Z")

</div>

> [@alice](#):
>
> @jameseb7 Be aware that `into_boxed_slice()` can be troublesome. It produces a fat pointer which must be split and put back together properly.

That is true. I was going to suggest the `as_ptr()` approach, then figured `into_boxed_slice()` would be better to avoid the `mem::forget()`, but forgot the need for an extra cast to thin the pointer.

I was surprised that there isn't a `Vec::into_ptr()`. There's [`Vec::into_raw_parts()`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_raw_parts), but that's not stable yet.

---

<div class="post-metadata">

**Author:** ![alice](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/alice/32/9777_2.png) [@alice](https://users.rust-lang.org/u/alice)\
**Post date:** [May 1, 2021, 10:20am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/5 "2021-05-01T10:20:10Z")

</div>

The challenge with `into_boxed_slice()` is that to pass it to C, you must take the `*mut [T]` you got from `Box::into_raw` and split it into:

- A pointer to the first element. Should have the type `*mut T`.
- It's length.

Then to deallocate it in Rust, you take those two pieces and turn them back into a `*mut [T]` using [`std::ptr::slice_from_raw_parts_mut`](https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html). Only at this point can you use [`Box::from_raw`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.from_raw). Because of this, it is not much simpler than the solution that uses `Vec` directly besides the fact that you don't need to store the capacity separately.

---

<div class="post-metadata">

**Author:** ![Yandros](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yandros/32/8136_2.png) [@Yandros](https://users.rust-lang.org/u/Yandros)\
**Post date:** [May 1, 2021, 1:15pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/6 "2021-05-01T13:15:04Z")

</div>

> [@helix\_tp](#):
>
> ```rust
> pub extern "C" fn MakeJob(???) -> ??? {
>     
> let my_struct = Vec::new();
> for struct_to_export in .... {
> my_struct.push(struct_to_export);
> }
> // export my_struct to C
> ....
> }
> 
> ```

For this task I heavily recommend you use `safer-ffi`, this way you won't have to write `unsafe` code on the Rust side, and will have a header generation for free 🙂 :

[![image](https://us1.discourse-cdn.com/flex019/uploads/rust_lang/original/3X/9/f/9f1179b68c4d7a9b827c08cca6603f95443937d9.jpeg)](https://getditto.github.io/safer_ffi/)

#### `src/lib.rs`

```diff
  #![allow(nonstandard_style] // to use other casing conventions unhindered.

+ use ::safer_ffi::prelude::*;

+ #[derive_ReprC]
  #[repr(C)]
  pub struct MyStruct {
      pub value : ::std::os::raw::c_int, 
      // ...
  }

- #[no_mangle] pub /* unsafe */ extern "C'
+ #[ffi_export]
  fn MakeJob ()
+ -> repr_c::Vec<MyStruct>
  {    
      let mut my_structs = Vec::new();
      for struct_to_export in ... {
          my_structs.push(struct_to_export);
      }
      // export my_struct to C
+ my_structs.into()
  }

```

- [More info](https://getditto.github.io/safer_ffi/motivation/repr-c-forall.html)

#### `Cargo.toml`

```toml
[lib]
crate-type = ["staticlib"] # or cdylib

```

```toml
[dependencies.safer-ffi]
version = "0.0.5"
features = ["proc_macros"]

```

- [More info](https://getditto.github.io/safer_ffi/usage/cargo-toml.html)

* * *

> **Header generation**
>
> #### `src/lib.rs`
> 
> ```rust
> #[cfg(feature = "generate-headers")]
> #[test]
> fn generate_headers ()
> -> ::std::io::Result<()>
> {
> ::safer_ffi::headers::builder()
> .to_file("headers.h")? // Feel free to rename to your liking (you could even read from an env var)
> .generate()
> }
> 
> ```
> 
> - [More info](https://getditto.github.io/safer_ffi/usage/lib-rs.html)
> 
> #### `Cargo.toml`
> 
> ```toml
> [features]
> generate-headers = ["safer-ffi/headers"]
> 
> ```
> 
> #### Shell
> 
> ```bash
> cargo test --features generate-headers -- generate_headers
> 
> ```
> 
> `headers.h` then contains:
> 
> ```cpp
> /*! \file */
> / *******************************************
> * *
> * File auto-generated by `::safer_ffi`. *
> * *
> * Do not manually edit this file. *
> * *
> ******************************************* /
> 
> #ifndef __RUST_CRATENAME__
> #define __RUST_CRATENAME__
> 
> #ifdef __cplusplus
> extern "C" {
> #endif
> 
> #include <stddef.h>
> #include <stdint.h>
> 
> typedef struct {
> 
> int32_t value;
> 
> } MyStruct_t;
> 
> /** \brief
> * Same as [`Vec<T>`][`rust::Vec`], but with guaranteed `#[repr(C)]` layout
> */
> typedef struct {
> 
> MyStruct_t * ptr;
> 
> size_t len;
> 
> size_t cap;
> 
> } Vec_MyStruct_t;
> 
> Vec_MyStruct_t MakeJob (void);
> 
> #ifdef __cplusplus
> } /* extern "C" */
> #endif
> 
> #endif /* __RUST_CRATENAME__ */
> 
> ```
> 
> * * *

![t-rec](https://us1.discourse-cdn.com/flex019/uploads/rust_lang/original/3X/f/8/f8c73455ead5ebeccc70da9bbaffd23ab331c39b.gif)

* * *

### _Quid_ of `free`ing the vec?

In this example you are giving ownership of the `Vec` to the (FFI) caller, but the FFI has no way of freeing the `Vec` contents correctly. So you should add a freeing function that just gives the ownership back to the Rust side, which will then free it with an implicit or explicit drop:

```rust
#[ffi_export]
fn free_vec (vec: repr_c::Vec<MyStruct>)
{
    drop(vec);
}

```

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [May 1, 2021, 4:03pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/7 "2021-05-01T16:03:29Z")

</div>

I would suggest to pass a slice to the C function, and if it wants to keep the data it has to copy it.

C

```nohighlight
void some_func(uint32* data, size_t len) {
   // can use `data` during this function call.
   // the pointer is not valid after the function returns
}

```

Rust

```rust
extern "C" {
    fn some_func(*const u32, usize);
}
fn call_some_func(data: &[u32]) {
    unsafe {
        some_func(data.ptr(), data.len());
    }
}

```

---

<div class="post-metadata">

**Author:** ![helix\_tp](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/helix_tp/32/11801_2.png) [@helix\_tp](https://users.rust-lang.org/u/helix_tp)\
**Post date:** [May 2, 2021, 5:11am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/8 "2021-05-02T05:11:36Z")

</div>

Hello,

Thank you for your answers,

I was implementing Alice's answer, when I saw Yandros's answer with the crate ::safe\_ffi, very simple to understand and to implement.

I give you the example code I made:

```nohighlight
#include "rust_rects.h"
#include <stdio.h>

void main(void){

    Vec_Rect_t myRect = hello_from_rust();
    for(int i=0;i<myRect.len;i++){
        printf("%d ",i);
        Rect_t *tmp_rect = myRect.ptr++;
        printf("%d\n",tmp_rect->x);
    }
    free_vec(myRect);
}

```

```nohighlight
use ::safer_ffi::prelude::*;
#[derive_ReprC]
#[repr(C)]
#[derive(Debug, Clone, Copy)]

pub struct Rect {
    pub x : ::std::os::raw::c_int, 
    pub y : ::std::os::raw::c_int, 
    pub w : ::std::os::raw::c_int, 
    pub h : ::std::os::raw::c_int, 
}

#[ffi_export]
pub extern "C" fn hello_from_rust() -> repr_c::Vec<Rect> {
    println!("hello from rust");
    let mut lst_rect = Vec::new();
    let my_rect = Rect {
        x : 0,
        y : 0,
        w : 128,
        h : 82,
    };

    lst_rect.push(my_rect);
    let my_rect = Rect {
        x : 127,
        y : 0,
        w : 128,
        h : 82,
    };
    lst_rect.push(my_rect);
    println!("rect : {:?}",lst_rect);
    lst_rect.into()
}

#[ffi_export]
fn free_vec (vec: repr_c::Vec<Rect>)
{
    drop(vec);
}
/// The following test function is necessary for the header generation.
#[::safer_ffi::cfg_headers]
#[test]
fn generate_headers() -> ::std::io::Result<()> {
    ::safer_ffi::headers::builder()
        .to_file("rust_rects.h")?
        .generate()
}

```

the Header is generated by ::safe\_ffi, so I don't put it.

Great job, it allowed me to understand better the solution of Alice.

@s3bk, I don't need to keep the data once the work is done by the Rust lib. But it could be useful for later.

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [May 2, 2021, 5:55am UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/9 "2021-05-02T05:55:42Z")

</div>

That looks good!

My proposal can't work here as Rust has to return a `Vec`/allocation to C.

---

<div class="post-metadata">

**Author:** ![helix\_tp](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/helix_tp/32/11801_2.png) [@helix\_tp](https://users.rust-lang.org/u/helix_tp)\
**Post date:** [May 2, 2021, 3:07pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/10 "2021-05-02T15:07:12Z")

</div>

bad news, ::safe\_ffi, does not work with a function of an impl (&self)

```rust
#[ffi_export]
pub extern "C" fn hello_from_rust(&self) -> repr_c::Vec<Rect> {
    println!("hello from rust");
    let mut lst_rect = Vec::new();
    let my_rect = Rect {
        x : 0,
        y : 0,
        w : 128,
        h : 82,
    };

    lst_rect.push(my_rect);
    let my_rect = Rect {
        x : 127,
        y : 0,
        w : 128,
        h : 82,
    };
    lst_rect.push(my_rect);
    println!("rect : {:?}",lst_rect);
    lst_rect.into()
}

```

```rust
no rules expected the token `&`
   --> src/lib.rs:102:22
    |
102 | pub fn hello_from_rust(&self) -> repr_c::Vec<HxObject> {
    | ^ no rules expected this token in macro call

error: aborting due to previous error

```

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [May 2, 2021, 3:15pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/11 "2021-05-02T15:15:18Z")

</div>

Why take `&self`? It isn't used at all.

You can also always write

```rust
struct Foo {}
impl Foo {
    pub fn bar(&self, arg: u32) { ... }
}

```

as

```rust
fn foo_bar(foo: &Foo, arg: u32) {
   foo.bar(arg);
}

```

---

<div class="post-metadata">

**Author:** ![helix\_tp](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/helix_tp/32/11801_2.png) [@helix\_tp](https://users.rust-lang.org/u/helix_tp)\
**Post date:** [May 2, 2021, 3:33pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/12 "2021-05-02T15:33:54Z")

</div>

It's because, by example Foo is not implemented by ::safe\_ffi (i suppose)

```rust
#[ffi_export]
    | ^^^^^^^^^^^^^ the trait `ReprC` is not implemented for `Foo`

```

---

<div class="post-metadata">

**Author:** ![Cerber-Ursi](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cerber-ursi/32/8315_2.png) [@Cerber-Ursi](https://users.rust-lang.org/u/Cerber-Ursi)\
**Post date:** [May 2, 2021, 4:12pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/13 "2021-05-02T16:12:25Z")

</div>

How do you expect to work it when taking `&self`, then? Method definition is essentially a syntax sugar, semantically it's no different from the free function with `&Self` being the first argument.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [July 31, 2021, 4:13pm UTC](https://users.rust-lang.org/t/pass-a-vec-from-rust-to-c/59184/14 "2021-07-31T16:13:01Z")

</div>

Closed on July 31, 2021, 4:13pm UTC

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
