How to return a dynamic-length vector to an extern "C" fn pub?

I want to return the vector to pub extern "C" fn. Since the vector is of arbitrary length, I think I need to return the structure with

  • pointer to vector and

  • number of elements in vector

My current code is:

extern crate libc;
use self::libc::{size_t, int32_t, int64_t};

// struct to represent an array and its size
#[repr(C)]
pub struct array_and_size {
    values: int64_t, // this is probably not how you denote a pointer, right?
    size: int32_t,
}

// The vector I want to return the address of is already in a Boxed struct, 
// which I have a pointer to, so I guess the vector is on the heap already. 
// Dunno if this changes/simplifies anything?
#[no_mangle]
pub extern "C" fn rle_show_values(ptr: *mut Rle) -> array_and_size {
    let rle = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };

    // this is the Vec<i32> I want to return 
    // the address and length of
    let values = rle.values; 
    let length = values.len();

    array_and_size {
       values: Box::into_raw(Box::new(values)),
       size: length as i32,
       }
}

#[derive(Debug, PartialEq)]
pub struct Rle {
    pub values: Vec<i32>,
}

The error I get is

$ cargo test
   Compiling ranges v0.1.0 (file:///Users/users/havpryd/code/rust-ranges)
error[E0308]: mismatched types
  --> src/rle.rs:52:17
   |
52 |         values: Box::into_raw(Box::new(values)),
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i64, found *-ptr
   |
   = note: expected type `i64`
   = note:    found type `*mut std::vec::Vec<i32>`

error: aborting due to previous error

error: Could not compile `ranges`.

To learn more, run the command again with --verbose.
-> exit code: 101

I published all this because I could not find an example of returning arrays / vectors in the extremely useful Rust FFI Omnibus .

Is this the best way to return an unknown size vector from Rust? How to fix my remaining compilation error? Thank!

q: , , , , , , . (, , , , , )? , , q, .

q2: ( Python), , . , , ? const , ?

Ps: C Rust, WTF.

+5
2
pub struct array_and_size {
    values: int64_t, // this is probably not how you denote a pointer, right?
    size: int32_t,
}

, . , values, - *mut int32_t.

, , C-, C "" ad-hoc , . API C

int32_t rle_values_size(RLE *rle);
int32_t *rle_values(RLE *rle);

(: , , , , , C).

Rust :

extern "C" fn rle_values_size(rle: *mut RLE) -> int32_t
extern "C" fn rle_values(rle: *mut RLE) -> *mut int32_t

size , ,

extern "C" fn rle_values(rle: *mut RLE) -> *mut int32_t {
    unsafe { &mut (*rle).values[0] }
}

Vec, C.

, C , C , ,

extern "C" fn rle_values_buf(rle: *mut RLE, buf: *mut int32_t, len: int32_t) {
    use std::{slice,ptr}
    unsafe {
        // Make sure we don't overrun our buffer length
        if len > (*rle).values.len() {
           len = (*rle).values.len()
        }
        ptr::copy_nonoverlapping(&(*rle).values[0], buf, len as usize);
    }
}

C

void rle_values_buf(RLE *rle, int32_t *buf, int32_t len);

() C- , C . ( , , ).

, "" C, mem::forget , C , , , .

C, *mut i32, i32, . from_raw_parts, to_vec , , Rust. , , from_raw_parts.

, , , . undefined, (, , GDB).

+5

C.


, C (int a[5] int[5] sizeof(a) 5 * sizeof(int)), .

, struct struct.

, , memcpy undefined ( undefined), valgrind .


- , .

, , .

:

  • C .
  • C

, : , , "", .

C

// file.h
int rust_func(int32_t* buffer, size_t buffer_length);

// file.rs
#[no_mangle]
pub extern fn rust_func(buffer: *mut libc::int32_t, buffer_length: libc::size_t) -> libc::c_int {
    // your code here
}

std::slice::from_raw_parts_mut, + ( 0s, ).

C

// file.h
struct DynArray {
    int32_t* array;
    size_t length;
}

DynArray rust_alloc();
void rust_free(DynArray);

// file.rs
#[repr(C)]
struct DynArray {
    array: *mut libc::int32_t,
    length: libc::size_t,
}

#[no_mangle]
pub extern fn rust_alloc() -> DynArray {
    let mut v: Vec<i32> = vec!(...);

    let result = DynArray {
        array: v.as_mut_ptr(),
        length: v.len() as _,
    };

    std::mem::forget(v);

    result
}

#[no_mangle]
pub extern fn rust_free(array: DynArray) {
    if !array.array.is_null() {
        unsafe { Box::from_raw(array.array); }
    }
}

a struct, . , Rust C , ; .

, .

// file.h
struct FixedArray {
    int32_t array[32];
};

// file.rs
#[repr(C)]
struct FixedArray {
    array: [libc::int32_t; 32],
}
+4

Source: https://habr.com/ru/post/1658696/


All Articles