MST

星途 面试题库

面试题:Rust与Python的高效互操作实现

在Rust与Python进行互操作场景下,假设要实现一个Python调用Rust编写的高性能计算模块,并且需要处理复杂的数据结构传递,你会如何设计并实现?请阐述主要步骤及可能用到的工具或库。
47.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 主要步骤
    • 编写Rust库
      • 使用cargo创建一个新的Rust库项目,例如cargo new --lib my_rust_lib
      • Cargo.toml文件中添加必要的依赖,如[lib]部分设置crate - type = ["cdylib"],以生成动态链接库供Python调用。
      • 编写高性能计算相关的Rust函数,这些函数要能处理复杂的数据结构。例如,如果需要处理自定义结构体,可以定义结构体并实现相关方法。例如:
#[derive(Debug, Clone)]
pub struct ComplexData {
    data: Vec<i32>,
    // 可以有更多复杂的成员,如嵌套结构体等
}

impl ComplexData {
    pub fn new(data: Vec<i32>) -> Self {
        ComplexData { data }
    }

    pub fn compute(&self) -> i32 {
        self.data.iter().sum()
    }
}
  • 导出Rust函数
    • 使用extern "C"关键字来指定函数的ABI(应用二进制接口)为C,这样Python可以通过C的方式调用Rust函数。例如:
#[no_mangle]
pub extern "C" fn compute_with_complex_data(data_ptr: *const ComplexData) -> i32 {
    let data = unsafe { &*data_ptr };
    data.compute()
}
  • 构建Rust库
    • 在项目根目录下执行cargo build --release,生成动态链接库文件(.so文件在Linux系统,.dll文件在Windows系统,.dylib文件在macOS系统)。
  • 在Python中调用
    • 使用ctypes库来加载动态链接库并调用其中的函数。首先,导入ctypesimport ctypes
    • 加载动态链接库,例如在Linux系统下:rust_lib = ctypes.CDLL('./target/release/libmy_rust_lib.so')
    • 定义与Rust中结构体对应的Python结构体。由于ctypes没有直接对应Rust结构体的方式,需要手动模拟:
import ctypes


class ComplexData(ctypes.Structure):
    _fields_ = [('data', ctypes.POINTER(ctypes.c_int)),
                ('data_len', ctypes.c_size_t)]


 - 调用Rust函数,例如:
rust_lib.compute_with_complex_data.argtypes = [ctypes.POINTER(ComplexData)]
rust_lib.compute_with_complex_data.restype = ctypes.c_int

data = [1, 2, 3]
data_array = (ctypes.c_int * len(data))(*data)
rust_data = ComplexData(data=data_array, data_len=len(data))

result = rust_lib.compute_with_complex_data(ctypes.byref(rust_data))
print(result)
  1. 可能用到的工具或库
    • Rust部分
      • cargo:Rust的构建工具,用于创建项目、管理依赖和构建项目。
      • cdylib crate - type:用于生成动态链接库,使得Rust代码可以被其他语言(如Python)调用。
    • Python部分
      • ctypes:Python的外部函数库,用于调用C动态链接库,这里可以间接调用Rust生成的以C ABI导出的动态链接库。

另一种方式:

  1. 主要步骤
    • 编写Rust库
      • 同上述步骤创建Rust库项目。
      • 这次使用pyo3库来简化与Python的交互。在Cargo.toml中添加pyo3依赖:pyo3 = { version = "0.18", features = ["extension - module"] }
      • 编写高性能计算函数及处理复杂数据结构。例如,对于上述ComplexData结构体:
use pyo3::prelude::*;

#[pyclass]
#[derive(Debug, Clone)]
pub struct ComplexData {
    data: Vec<i32>,
}

#[pymethods]
impl ComplexData {
    #[new]
    pub fn new(data: Vec<i32>) -> Self {
        ComplexData { data }
    }

    pub fn compute(&self) -> i32 {
        self.data.iter().sum()
    }
}

#[pymodule]
fn my_rust_lib(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<ComplexData>()?;
    Ok(())
}
  • 构建Rust库
    • 执行cargo build --release,生成Python扩展模块(.so文件在Linux和macOS系统,.pyd文件在Windows系统)。
  • 在Python中调用
    • 直接导入生成的模块,例如:
import my_rust_lib

data = [1, 2, 3]
rust_data = my_rust_lib.ComplexData(data)
result = rust_data.compute()
print(result)
  1. 可能用到的工具或库
    • Rust部分
      • cargo:构建工具。
      • pyo3:一个Rust库,用于创建Python扩展模块,极大简化了Rust与Python的互操作,能方便地处理复杂数据结构传递,如自定义结构体等。
    • Python部分:无额外特殊库,直接导入生成的Rust扩展模块即可。