Get Vec from C API call

I'm working on a wrapper for GraphBLAS

I need to extract 2 Vec from a C call that has the following binding

extern "C" {
    pub fn GrB_Vector_extractTuples_FP64(
        I: *mut GrB_Index,
        X: *mut f64,
        nvals: *mut GrB_Index,
        v: GrB_Vector,
    ) -> GrB_Info;
}

This is how the function is called from the C API

    X = malloc (n * sizeof (double)) ;
    I = malloc (n * sizeof (GrB_Index)) ;
    CHECK (I != NULL && X != NULL, GrB_OUT_OF_MEMORY) ;
    GrB_Index nvals = n ;        
    OK (GrB_Vector_extractTuples (I, X, &nvals, r)) ;

I would need a function to return a tuple (Vec, Vec), my attempts mostly got me with invalid memory reference errors.

A Rust vector must be allocated by Rust. You can't turn malloc'ed arrays into a Vec. Allocate the memory in Rust.

2 Likes

If you don't need vecs, the other correct way to do this would be to write a wrapper which dereferences into a slice. Something like

struct GrbVec { ... }
impl Deref for GrbVec {
    type Target = [f64];
    fn deref(&self) -> &[f64] {
        // code to construct a reference to the malloced memory
    }
}
impl Drop for GrbVec {
    fn drop(&mut self) {
        // call the proper C api to deallocate memory
    }
}

See also the nomicon chapter on FFI, if you haven't already read it: FFI - The Rustonomicon

let mut I = Vec::<GrB_Index>::with_capacity(nvals);
let mut X = Vec::<f64>::with_capacity(nvals);
unsafe {
    GrB_Vector_extractTuples_FP64(
        I.as_mut_ptr(),
        X.as_mut_ptr(),
        &mut nvals,
        GrB_Vector /* ... */,
    );
    /* Check that the result code is OK (skipped here) */

    I.set_len(nvals);
    X.set_len(nvals);
}
1 Like

Yes, as pointed above this was in the nomicon.

Thanks

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.