首页 > 解决方案 > 如何使用 Rust 的 FFI 从 C 中获取输出字符串参数?

问题描述

我一直在用 Rust 深入研究 FFI,虽然有一些有用的帖子和文档关于传入字符串,有时还会从 C 函数中获取字符串作为返回值,但我看不到任何获取 out 参数的方法. 为了让我的脚湿透,我试图访问一个 C 库,该库公开了一个声明为的函数:

unsigned char *some_func(
    const unsigned char *key,
    unsigned int klen,
    const unsigned char *src,
    unsigned char *dest,
    unsigned int slen);

我认为它应该大致声明为:

use libc;

extern "C" {
    fn some_func(
        key: *const libc::c_uchar,
        klen: libc::c_uint,
        src: *const libc::c_uchar,
        dest: *mut libc::c_uchar,
        slen: libc::c_uint) -> *mut libc::c_uchar;
}

// wrapper
pub fn wrapped_func(key: &str, src: &str) -> String {
    unsafe {
        let key_len = key.len() as u32;
        let key = std::ffi::CString::new(key).unwrap();

        let src_len = src.len() as u32;
        let src = std::ffi::CString::new(src).unwrap();

        let key_ptr = key.as_ptr();
        let src_ptr = src.as_ptr();

        let mut dest: *mut std::ffi::CStr;

        let result = PC1(key_ptr, key_len, src_ptr, &mut dest, src_len);
        //                                          ^^^^^^^^^ expected `u8`, found *-ptr
        key_ptr = ptr::null();
        src_ptr = ptr::null();

        let result_string = if let Ok(s) = result.to_str() {
           String::from(s)
        } else {
           String::new()
        };

        dest = ptr::null();

        result_string
}

我有几个问题:

  1. 我不知道如何正确声明dest为我的输出字符串。获取输出字符串的正确方法是什么?从Wrapping Unsafe C Libraries in Rust看来,我需要将其视为CStr

对于const char *从 C 函数中获取 a 并希望将其转换为 Rust 可以使用的东西的情况,您需要确保它不为空,然后将其转换为&CStr具有适当生命周期的 a。如果你不知道如何表达一个合适的生命周期,最安全的做法是立即将其转换为拥有String

  1. C 代码 - 因此我的 extern 函数 - 将字符串声明为unsigned char *,但是当我尝试调用时,我在u8和之间存在类型不匹配i8。只是切换externto是可以接受的c_char,还是这很危险?

  2. 是否设置key_ptr = ptr::null()了正确的方式(以及所有需要的方式)来安全地释放内存?

标签: rustffi

解决方案


推荐阅读