Skip to content

Commit

Permalink
Add a function to free slice
Browse files Browse the repository at this point in the history
  • Loading branch information
yutannihilation committed Sep 16, 2020
1 parent dda013c commit 97b3628
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/myrustlib/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ typedef struct

char * string_from_rust();
char * string_from_rust2(const char*);

Slice rev_slice(Slice);
void free_slice(Slice);

int32_t random_number();
void run_threads();

Expand Down
1 change: 1 addition & 0 deletions src/myrustlib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ pub use hello::string_from_rust2;
pub use random::random_number;
pub use mythreads::run_threads;
pub use slice::rev_slice;
pub use slice::free_slice;
pub use slice::Slice;
13 changes: 12 additions & 1 deletion src/myrustlib/src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct Slice {
}

#[no_mangle]
pub extern fn rev_slice(s: Slice) -> Slice {
pub extern "C" fn rev_slice(s: Slice) -> Slice {
// convert from Slice to Rust slice
let s = unsafe { std::slice::from_raw_parts_mut(s.data, s.len as _) };

Expand All @@ -24,3 +24,14 @@ pub extern fn rev_slice(s: Slice) -> Slice {
len: len as _,
}
}

// c.f. https://users.rust-lang.org/t/how-to-return-byte-array-from-rust-function-to-ffi-c/18136/4
#[no_mangle]
pub extern "C" fn free_slice(s: Slice) {
// convert to Rust slice
let s = unsafe { std::slice::from_raw_parts_mut(s.data, s.len as _) };
let s = s.as_mut_ptr();
unsafe {
Box::from_raw(s);
}
}
12 changes: 9 additions & 3 deletions src/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Import C headers for rust API
#include "myrustlib/api.h"

// Need to include to use memcpy()
#include <string.h>

// Actual Wrappers
SEXP hello_wrapper(){
return Rf_ScalarString(Rf_mkCharCE(string_from_rust(), CE_UTF8));
Expand All @@ -20,11 +23,14 @@ SEXP rev_wrapper(SEXP x){
Slice s_rev = rev_slice(s);

SEXP out = PROTECT(Rf_allocVector(REALSXP, s_rev.len));
for (int i = 0; i < s_rev.len; i++) {
SET_REAL_ELT(out, i, s_rev.data[i]);
}
memcpy(REAL(out), s_rev.data, s.len * sizeof(double));
// AS soon as the Rust-allocated memory become no longer in use, free it.
// Since Rust's allocator is different from C's allocator, this needs to be
// freed on C's side.
free_slice(s_rev);
UNPROTECT(1);


return out;
}

Expand Down

0 comments on commit 97b3628

Please sign in to comment.