I want to generate 6 random numbers, push them onto a vector, then use rustc_serialize
to encode that vector as a JSON string to be consumed by NodeJS.
Thank you Wesley Wiser for giving me a big clue with CString
. I found the answer in The Rust FFI Omnibus.
The memory for my expected JSON string was being deallocated before my NodeJS program could access it, whether I returned the JSON string or returned a CString
.
Here's my solution based on that article. To other novice programmers, please keep in mind that my solution may or may not be ideal:
extern crate rand;
extern crate rustc_serialize;
extern crate libc;
use libc::c_char;
use rand::{OsRng, Rng};
use std::ffi::CString;
use rustc_serialize::json;
#[no_mangle]
pub extern "C" fn generate() -> *mut c_char {
let choices: [u8; 6] = [1, 2, 3, 4, 5, 6];
let mut rand_vec: Vec = Vec::new();
let mut rng = match OsRng::new() {
Ok(t) => t,
Err(e) => panic!("Failed to create OsRng!, {}", e),
};
for _ in 0..6 {
rand_vec.push(*rng.choose(&choices).unwrap());
}
let json_string = CString::new(json::encode(&rand_vec).unwrap()).unwrap();
json_string.into_raw()
}
#[no_mangle]
pub extern "C" fn free_memory(pointer: *mut c_char) {
unsafe {
if pointer.is_null() {
return;
}
CString::from_raw(pointer)
};
}
var ffi = require('ffi');
var path = require('path');
var lib = ffi.Library(path.join(__dirname,
'./ffi/generate_6_rand.dll'), {
generate: [ 'char *' , [ ]],
free_memory: ['void', ['char *']]
});
var json_string = lib.generate();
var save_json = JSON.parse(json_string.readCString());
console.log( json_string.readCString()); // Output: [6,1,6,4,1,4]
lib.free_memory(json_string);
console.log(json_string.readCString()); // Output: ��x�
I set up two console.log
s to show what the output before and after deallocation.