Search code examples
rustdllffinode-ffi

use safer-ffi in Rust to created dll,analytic struct fail


use ffi-napi to test DLL, create a strcut and call the DLL method, analyze Struct is fail -> process_waave_info,I don't know where to make a mistake

test.mjs

import ffi from "ffi-napi";
import ref from "ref-napi";
import ref_struct from "ref-struct-di";
import ref_array from "ref-array-di";

const StructType = ref_struct(ref);
const ArrayType = ref_array(ref);

const WavesConfig = StructType({
  gain: ref.types.float,
  speed: ref.types.float,
  cell_mg: ref.types.float,
  canvas_width: ref.types.float,
  canvas_height: ref.types.float,
  canvas_position: ref.types.int,
});
const FloatArray = ArrayType(ref.types.float);

const WavesInfo = StructType({
  config: WavesConfig,
  // wave_from_list: FloatArray,
});

const libm = ffi.Library("./target/release/wave_from_tools.dll", {
  get_sens_to_px: ["double", ["double", "double"]],
  process_waave_info: ["void", [WavesInfo]],
});

const wavesInfo = new WavesInfo({
  config: new WavesConfig({
    gain: 3.0,
    speed: 1.0,
    cell_mg: 4.0,
    canvas_width: 600.2,
    canvas_height: 800.4,
    canvas_position: 2,
  }),
  // wave_from_list: new FloatArray([1.0, 2.0, 3.4, 4, 5, 6, 7, 8]),
});

console.log("get_sens_to_px", libm.get_sens_to_px(1.0, 8.0)); // success

try {
  libm.process_waave_info(wavesInfo); // fail
} catch (e) {
  console.log('error', e);
}

lib.rs

use safer_ffi::prelude::*;
use safer_ffi::Vec;

#[ffi_export]
pub fn get_sens_to_px(gain: f64, cell_mg: f64) -> f64 {
    gain * cell_mg
}

#[derive_ReprC]
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum CanvasStartPostion {
    LeftTop,
    LeftBottom,
    RightTop,
    RightBottom,
}

#[derive_ReprC]
#[repr(C)]
#[derive(Debug)]
pub struct WavesConfig {
    pub gain: f64,
    pub speed: f64,
    pub cell_mg: f64,
    pub canvas_width: f64,
    pub canvas_height: f64,
    pub canvas_position: CanvasStartPostion,
}

#[derive_ReprC]
#[repr(C)]
#[derive(Debug)]
pub struct WavesInfo {
    pub config: WavesConfig,
    // pub wave_from_list: Vec<f64>,
}


#[ffi_export]
pub fn process_waave_info(waves_info: WavesInfo) {
    println!("waves_info: {:?}", waves_info);
    // println!("sens_px: {:}", sens_px);
}

output

❯ pnpm run test

> [email protected] test E:\Gitte\wave_from_tools
> node test/test_dll.mjs

get_sens_to_px 8
waves_info: WavesInfo { config: WavesConfig { gain: 0.007812501869921107, speed: 1.0168770850969774e20, cell_mg: 4.809981246e-314, canvas_width: -3.788539966563847e-270, canvas_height: 6.9514354333476e-310, canvas_position: LeftTop } }
 ELIFECYCLE  Test failed. See above for more details.

expecting

I checked the document and search the corresponding questions and found that it was not related to it.

expecting is this:

❯ pnpm run test

> [email protected] test E:\Gitte\wave_from_tools
> node test/test_dll.mjs

get_sens_to_px 8
waves_info: WavesInfo { config: WavesConfig { gain: 3.0, speed: 1.0, cell_mg: 4.0, canvas_width: 600.2, canvas_height: 800.4, canvas_position: RightTop } }

Solution

  • Need to modify the following places:

    const WavesConfig = StructType({
      gain: ref.types.double,
      speed: ref.types.double,
      cell_mg: ref.types.double,
      canvas_width: ref.types.double,
      canvas_height: ref.types.double,
      canvas_position: ref.types.int,
    });
    

    Change the ref.types.float to ref.types.double

    ➜ pnpm run test
    
    > [email protected] test E:\Gitte\wave_from_tools
    > node test/test_dll.mjs
    
    get_sens_to_px 8
    get_sens_to_px 4
    waves_info: WavesInfo { config: WavesConfig { gain: 3.0, speed: 1.0, cell_mg: 4.0, canvas_width: 600.2, canvas_height: 800.4, canvas_position: LeftBottom } }