【问题标题】:How do I convert arrays to a snips-nlu-rs whitelist or blacklist?如何将数组转换为 snips-nlu-rs 白名单或黑名单?
【发布时间】:2020-01-24 00:03:46
【问题描述】:

我使用 snips 并构建了一个 C 库。我想用 Rust 将库连接到我的 Node 环境。

JavaScript

var ffi = require('ffi');
const ArrayType = require('ref-array');
var nlu = require('./nlu');

const StringArray = ArrayType('string');


var nlulib = '../cargo/target/x86_64-apple-darwin/release/libp_public_transport_nlu.dylib'

var nlu = ffi.Library(nlulib, {
    "load": ['pointer', ['string']],
    "execute": ['string', ['pointer', 'string', StringArray]]
});


var ptrToEngine = nlu.load("../snips_public_transport_engine");
var responseNLU = nlu.execute(ptrToEngine, "myQuery", ['bestIntent'], ['worstIntent']);

生锈

#[no_mangle]
pub extern "C" fn execute(engine_pointer: *mut SnipsNluEngine, query: *const c_char, whitelist: &[u8], blacklist: &[u8]) -> CString {    
    let query_c_str = unsafe { CStr::from_ptr(query) };
    let query_string = match query_c_str.to_str().map(|s| s.to_owned()){
        Ok(string) => string,
        Err(e) => e.to_string()
    };

    let engine = unsafe {
        assert!(!engine_pointer.is_null());
        &mut *engine_pointer
    };

    let result = engine.parse(query_string.trim(), None, None).unwrap();
    let result_json = serde_json::to_string_pretty(&result).unwrap();

    CString::new(result_json).unwrap()
}

engine.parse函数expects Into<Option<Vec<&'a str>>> as a parameter instead of None,所以我需要将白名单和黑名单转换成这种格式。

【问题讨论】:

  • 很难回答您的问题,因为它不包含minimal reproducible example。我们无法分辨代码中存在哪些 crate(及其版本)、类型、特征、字段等。如果您尝试在Rust Playground 上重现您的错误,如果可能的话,这将使我们更容易为您提供帮助,否则在全新的 Cargo 项目中,然后在edit 您的问题中包含附加信息。您可以使用Rust-specific MRE tips 来减少您在此处发布的原始代码。谢谢!
  • 值得注意的是,您的问题似乎与 JavaScript 或 C 甚至 FFI 无关。看起来您应该能够大幅减少代码,同时制作一个示例,以便任何人都可以轻松看到错误。

标签: rust snips


【解决方案1】:

经过一番努力,我找到了解决方案。我知道,这不会是有史以来最好的,但它是一个解决方案:)

pub extern "C" fn execute(engine_pointer: *mut SnipsNluEngine, query: *const c_char, whitelist: *const *const c_char) -> CString {
    let query_c_str = unsafe { CStr::from_ptr(query) };
    let query_string = match query_c_str.to_str().map(|s| s.to_owned()){
        Ok(string) => string,
        Err(e) => e.to_string()
    };

    let engine = unsafe {
        assert!(!engine_pointer.is_null());
        &mut *engine_pointer
    };


    // count length of whitelist
    let mut whitelist_count = 0;
    let mut wc = whitelist;
    unsafe {
        while *wc != std::ptr::null() {
            whitelist_count += 1;
            wc = wc.offset(1);
        }
    }

    // get single elements pointer from pointer
    let sliced_whitelist = unsafe { slice::from_raw_parts(whitelist, whitelist_count) };

    // get string for every pointer
    let mut string_list_whitelist: Vec<String> = vec![];

    for i in 0..whitelist_count {
        let whitelist_element = sliced_whitelist[i];
        let whitelist_value = unsafe { CStr::from_ptr(whitelist_element) };

        let string_whitelist: String = match whitelist_value.to_str().map(|s| s.to_owned()){
            Ok(string) => string,
            Err(e) => e.to_string()
        };

        string_list_whitelist.insert(0, string_whitelist);
    }

    let mut snips_whitelist: Vec<&str> = vec![];

    for i in 0..whitelist_count {
        let whitelist_element_str: &str = &string_list_whitelist[i][..];

        snips_whitelist.insert(0, whitelist_element_str);
    }


    // create an optional for the whitelist
    let mut snips_whitelist_optional: Option<Vec<&str>> = None;

    if whitelist_count != 0 {
        snips_whitelist_optional = Some(snips_whitelist);
    }

    // parsing
    let result = engine.parse(query_string.trim(), snips_whitelist_optional, snips_blacklist_optional).unwrap();
    let result_json = serde_json::to_string_pretty(&result).unwrap();

    CString::new(result_json).unwrap()

}

提示:必须在白名单字符串数组的末尾发送 Nullpointer(例如 ref.NULL)。或者,您可以将数组长度作为参数发送,而不是计算列表长度。

【讨论】:

猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
相关资源
最近更新 更多