MST

星途 面试题库

面试题:Rust与C ABI兼容性下的类型转换与数据传递

在Rust和C的交互场景中,Rust的`String`类型和C的`char *`类型如何进行安全且高效的转换?当从C调用Rust函数传递一个`char *`数组,Rust函数如何正确接收并处理?给出具体实现步骤及代码示例。
41.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Rust的String和C的char *转换

  1. 从Rust的String转换为C的char *
    • 在Rust中,String是一个动态分配的字符串类型。要转换为char *,通常需要将String转换为CString(来自libc::CString),因为普通的String可能包含空字符,而C字符串以空字符结尾。
    • CString可以通过as_ptr方法获取一个*const c_charc_charlibc中定义的C字符类型,对应C的char),这就类似于C的char *
    • 示例代码:
use std::ffi::CString;
use libc::c_char;

fn string_to_c_str(s: String) -> *const c_char {
    let c_str = CString::new(s).expect("Failed to convert String to CString");
    c_str.as_ptr()
}
  1. 从C的char *转换为Rust的String
    • 可以使用CStr(来自libc::CStr)来安全地处理C字符串,然后将其转换为String
    • 示例代码:
use std::ffi::CStr;
use libc::c_char;

fn c_str_to_string(c_str: *const c_char) -> String {
    let c_str = unsafe { CStr::from_ptr(c_str) };
    c_str.to_str().expect("Failed to convert CStr to &str").to_string()
}

从C调用Rust函数传递char *数组,Rust函数接收并处理

  1. 定义Rust函数
    • 使用extern "C"修饰符来标记函数,以便C代码可以调用。
    • 函数参数可以是*const c_char,表示C字符串。
    • 示例代码:
use std::ffi::CStr;
use libc::c_char;

#[no_mangle]
pub extern "C" fn process_c_string(c_str: *const c_char) {
    let c_str = unsafe { CStr::from_ptr(c_str) };
    if let Ok(s) = c_str.to_str() {
        println!("Processed string: {}", s);
    } else {
        println!("Invalid UTF - 8 string");
    }
}
  1. C代码调用
    • 在C代码中,需要链接生成的Rust库(通常是动态库.so或静态库.a)。
    • 示例C代码:
#include <stdio.h>
#include <stdlib.h>

// 假设Rust函数定义在一个名为libexample.so的库中
// 函数声明
extern void process_c_string(const char*);

int main() {
    const char* str = "Hello from C";
    process_c_string(str);
    return 0;
}

需要注意的是,在实际使用中,从Rust获取的*const c_char指针在使用完后,不能在Rust外部释放,因为Rust的内存管理和C的内存管理方式不同。同样,从C传递给Rust的char *指针,Rust函数也不应该释放,除非明确约定由Rust管理内存。