Zero-copy FFI structures

I am trying to access the C-style vector from Rust (for Rizin's Rust bindings), currently the conversion happens like this:

/// A generic converter from RzVector to Vec (with a type conversion function)
macro_rules! rzpvector_to_vec {
    ($fn_name:ident, $base_type:ident, $return_type:ident, $conversion_fn:ident) => {
        fn $fn_name(core: &RizinCore, pvec: *mut RzPVector) -> Vec<$return_type> {
            let mut vec: Vec<$return_type> = Vec::new();
            unsafe {
                while !rz_pvector_empty(pvec) {
                    let element = rz_pvector_pop_front(pvec) as *mut $base_type;
                    if let Some(el) = $conversion_fn(core, element) {

Where RzPVector is the C (see complete implementation of it in librz/util/vector.c and librz/include/rz_vector.h) structure like this:

typedef struct rz_vector_t {
	void *a; //< a continuous chunk of memory where all elements are stored sequentially
	size_t len;
	size_t capacity;
	size_t elem_size;
	RzVectorFree free;
	void *free_user;
} RzVector;

// RzPVector directly wraps RzVector for type safety
typedef struct rz_pvector_t {
	RzVector v;
} RzPVector;

Is there any way to somehow impose Rust Vec-like (at least simple iteration, etc) traits on top of this structure without copying? Because creating a new Vec works fine for small structures but copying gets problematic on really huge RzPVectors.

Yes, you can implement traits for any type in Rust. An "FFI type" is not special to the compiler – it just usually means that it's #[repr(C)] and it will be passed a lot to unsafe functions, neither of which affects its ability to implement traits.

I found this crate, which roughly solves my problem - zerovec without the need to reimplement all traits by myself.

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.