不要这样做:
#[no_mangle]pub extern fn my_func(my_vec: Vec<i32>) -> i32 { ... }基本上,您 从不 希望接受或返回
extern函数中的任意Rust对象,仅是
Repr。相反,您应该接受C可以表示的内容。正如6502所说的,对于这种特殊情况,最好的主意是接受一个指针和一个长度。
Vec从概念上讲,Rust的指针指向数据,计数 和容量
。您可以
Vec通过添加或删除对象来修改,这可能导致重新分配。这是双重不利的,因为Python和Rust可能使用彼此不兼容的不同分配器。分段错误就是这样!你真的想要
切片 。
相反,在Rust方面执行以下操作:
extern crate libc;use libc::{size_t,int32_t};use std::slice;#[no_mangle]pub extern fn my_func(data: *const int32_t, length: size_t) -> int32_t { let nums = unsafe { slice::from_raw_parts(data, length as usize) }; nums.iter().fold(0, |acc, i| acc + i)}也就是说,您正在使用保证匹配的C类型,然后将指针和长度转换为Rust知道如何处理的东西。
我不是Pythonista,但是这个经过拼凑的代码(在“如何使用ctypes将Python列表转换为C数组?”的帮助下)似乎可以与上面的Rust一起使用:
import ctypeslib = ctypes.cdll.LoadLibrary("./target/debug/libpython.dylib")lib.my_func.argtypes = (ctypes.POINTER(ctypes.c_int32), ctypes.c_size_t)list_to_sum = [1,2,3,4]c_array = (ctypes.c_int32 * len(list_to_sum))(*list_to_sum)print lib.my_func(c_array, len(list_to_sum))当然,您可能希望将其包装起来以使其对您的代码调用者更好。



