能否从Rust向C传递数组?Rust字符串数组C调用异常问题
解决Rust向C传递数组只返回第一个元素的问题
这是因为你的C函数声明和Rust实际返回的类型不匹配导致的,咱们一步步来搞定:
问题根源
你在Rust里定义的函数返回的是[*const c_char; 2]——也就是包含两个const char*的固定大小数组,但在C里你却把函数声明成了返回单个char*。C在调用时只会读取返回值的第一个指针,第二个指针的内容直接被忽略,所以你只能拿到"Hello"。
正确的解决步骤
1. 修正C函数声明
把C头文件里的声明改成匹配Rust返回类型的形式,你有两种选择:
- 更通用的指针指针形式(C里数组作为返回值会自动退化为指针):
#include <stdint.h> extern const char** string_from_rust(void); // 别忘了加释放内存的函数声明 extern void free_rust_strings(const char* strings[2]);
- 明确数组大小的形式(部分编译器支持):
extern const char* string_from_rust(void)[2];
2. 补充Rust的内存释放函数
你用std::mem::forget跳过了Rust的自动内存管理,这些字符串的内存不会被自动回收,必须手动写一个Rust函数来释放,绝对不能用C的free——因为内存是Rust分配器分配的,和C的分配器不兼容。
修改后的Rust代码:
use std::ffi::CString; use std::os::raw::c_char; #[no_mangle] pub extern "C" fn string_from_rust() -> [*const c_char; 2] { let s = CString::new("Hello").unwrap(); let t = CString::new("World").unwrap(); let p = s.as_ptr(); let w = t.as_ptr(); std::mem::forget(s); std::mem::forget(t); [p, w] } #[no_mangle] pub extern "C" fn free_rust_strings(strings: [*const c_char; 2]) { // 重新包装成CString并自动drop,就能释放内存 unsafe { if !strings[0].is_null() { CString::from_raw(strings[0] as *mut c_char); } if !strings[1].is_null() { CString::from_raw(strings[1] as *mut c_char); } } }
3. C端正确调用示例
现在你可以在C里正常获取两个字符串,用完记得调用释放函数:
#include <stdio.h> #include "your_header.h" int main() { const char** strings = string_from_rust(); printf("第一个字符串:%s\n", strings[0]); printf("第二个字符串:%s\n", strings[1]); // 释放内存,避免泄漏 free_rust_strings((const char*[2]){strings[0], strings[1]}); return 0; }
额外提醒
- 如果你传递的是动态长度的数组,建议同时返回数组的长度,方便C端遍历;
- 永远不要用C的内存管理函数操作Rust分配的内存,反之亦然,否则会导致内存错误或泄漏。
内容的提问来源于stack exchange,提问作者Carl
相关产品推荐
相关产品推荐

