How to return string value from a Rust FFI function in NodeJS?

前端 未结 1 1577
清歌不尽
清歌不尽 2021-01-23 04:26

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.



        
相关标签:
1条回答
  • 2021-01-23 04:52

    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:

    Rust

    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<u8> = 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)
        };
    }
    

    NodeJS

    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.logs to show what the output before and after deallocation.

    0 讨论(0)
提交回复
热议问题