You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:32:30