【问题标题】:Reading pointer from Rust in C从 C 中的 Rust 读取指针
【发布时间】:2021-07-26 09:35:47
【问题描述】:

我正在尝试通过创建 DLL 并将其连接到我的 C 项目来将 Rust 与 C 一起使用。现在,我在传递指针方面遇到了一些麻烦。

我写了一些例子并试图理解这个问题:

#[no_mangle]
pub extern fn hex2ascii(hex_len : usize, hex_in: *const u8, ascii_len : &mut usize, ascii_out : *mut c_char) -> *mut c_char {
    let mut out_str = String::new();
    
    unsafe {
        let array = std::slice::from_raw_parts(hex_in, hex_len);
        for i in array
        {
             out_str.push_str(&(format!("0x{:02X?}, ", i)));
        }
        println!("{ }", out_str);

        out_str.pop();
        *ascii_len = out_str.len();
        ascii_out = std::ffi::CString::new(out_str.clone()).unwrap().into_raw();
        return ascii_out;
    }

}

如果我尝试用return std::ffi::CString::new(out_str.clone()).unwrap().into_raw(); 替换return ascii_out;,它将正常工作。但我想将指针放在 ascii_out 中并在我的 C-proj 中读取它。

附:在 C++ 上添加一个简单的测试

    unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
    size_t size = 0;
    int size2 = sizeof(arr);
    char *out = hex2ascii(size2, arr, &size);
    for (int i = 0; i < size - 1; i++)
    {
        std::cout << out[i];
    }
    std::cout << std::endl;

但是,我想要这样的东西:

    unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
    size_t size = 0;
    int size2 = sizeof(arr);
    char out[255];           // here can be any size
    int rc = hex2ascii(size2, arr, &size, out);
    for (int i = 0; i < size - 1; i++)
    {
        std::cout << out[i];
    }
    std::cout << std::endl;

【问题讨论】:

  • 你能把你要调用它的 C 部分包括进来吗?很难判断您是希望该函数分配自己的输出缓冲区还是将结果写入ascii_out指向的缓冲区...

标签: c++ c pointers rust


【解决方案1】:

如果您可以正确构建和链接所有内容,那么您正在寻找的解决方案就在 std::ptr::copy 中。它会将 N 个字节从源复制到目标。

"std::ptr::copy 在语义上等价于 C 的 memmove, 但交换了参数顺序。”

如果您偶然发现了这篇文章,并且没有链接或编译工作 - 我建议您查看this github repo

附带说明 - 如果您知道内存没有重叠,建议改用 std::ptr::copy_nonoverlapping

use std::ffi::CString;

use std::os::raw::c_char;

#[no_mangle]
pub extern "C" fn hex2ascii(
    hex_in: *const u8,
    hex_len : usize,
    ascii_len : &mut usize,
    ascii_out : *mut c_char
) -> *mut c_char 
{
    let mut out_str = String::new();
    
    unsafe {
        let array = std::slice::from_raw_parts(hex_in, hex_len);
        for i in array {
             out_str.push_str(&(format!("0x{:02X?}, ", i)));
        }

        out_str.pop();
        *ascii_len = out_str.len();
        let c_str_out = CString::new(out_str).unwrap();

        std::ptr::copy(c_str_out.as_ptr(), ascii_out, *ascii_len); // Copy N bytes to dst from src
        
        return c_str_out.into_raw();
    }
}
// note I changed the parameter order in rust.
// this code reflects those changes.

int main() {
    unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
    size_t size = 0;
    int size2 = sizeof(arr);
    char out[255];           // here can be any size
    char * old_way = hex2ascii(arr, size2, &size, out);
    for (int i = 0; i < size - 1; i++)
    {
        std::cout << out[i];
    }
    std::cout << std::endl;
}

【讨论】:

    猜你喜欢
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多