Skip to content

Commit 97b3628

Browse files
Add a function to free slice
1 parent dda013c commit 97b3628

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

src/myrustlib/api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ typedef struct
1313

1414
char * string_from_rust();
1515
char * string_from_rust2(const char*);
16+
1617
Slice rev_slice(Slice);
18+
void free_slice(Slice);
19+
1720
int32_t random_number();
1821
void run_threads();
1922

src/myrustlib/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ pub use hello::string_from_rust2;
1414
pub use random::random_number;
1515
pub use mythreads::run_threads;
1616
pub use slice::rev_slice;
17+
pub use slice::free_slice;
1718
pub use slice::Slice;

src/myrustlib/src/slice.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub struct Slice {
88
}
99

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

@@ -24,3 +24,14 @@ pub extern fn rev_slice(s: Slice) -> Slice {
2424
len: len as _,
2525
}
2626
}
27+
28+
// c.f. https://users.rust-lang.org/t/how-to-return-byte-array-from-rust-function-to-ffi-c/18136/4
29+
#[no_mangle]
30+
pub extern "C" fn free_slice(s: Slice) {
31+
// convert to Rust slice
32+
let s = unsafe { std::slice::from_raw_parts_mut(s.data, s.len as _) };
33+
let s = s.as_mut_ptr();
34+
unsafe {
35+
Box::from_raw(s);
36+
}
37+
}

src/wrapper.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
// Import C headers for rust API
66
#include "myrustlib/api.h"
77

8+
// Need to include to use memcpy()
9+
#include <string.h>
10+
811
// Actual Wrappers
912
SEXP hello_wrapper(){
1013
return Rf_ScalarString(Rf_mkCharCE(string_from_rust(), CE_UTF8));
@@ -20,11 +23,14 @@ SEXP rev_wrapper(SEXP x){
2023
Slice s_rev = rev_slice(s);
2124

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

33+
2834
return out;
2935
}
3036

0 commit comments

Comments
 (0)