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

Rust通过FFI调用Fortran库时内存访问违规问题求助

问题分析与解决方案

核心问题:参数传递不匹配导致栈布局错乱

你的内存访问错误直接源于Rust代码中数组参数的传递方式错误,以及可能存在的函数名修饰不匹配,和Fortran的1索引特性无关。

具体错误点拆解

  1. 数组传递类型错误
    Fortran老旧库的数组形参ARRAY(LENGTH)期望接收的是数组首元素的单指针(和VB.net中ByRef ARRAY As Double的传递逻辑一致,VB实际传递的是数组第一个元素的地址)。但你在Rust中传递的是&mut [f64]——这是Rust的胖指针(包含指针+数组长度两个字段,占16字节),而非单指针(8字节)。
    这种差异会导致栈上后续参数的位置整体偏移8字节,Fortran读取到的参数值完全错乱:比如原本的LENGTH参数会被替换成切片的长度值,当Fortran尝试将这个数值当作指针去访问内存时,就会出现0x00000079(对应length=121)这类非法地址访问错误。

  2. 函数名修饰可能不匹配
    你使用的_FD_TEMP_DIST@24是32位Windows平台下stdcall调用约定的函数名修饰规则(@24表示参数总字节数),但如果你的运行环境是64位Windows,Fortran库导出的函数名应该是无修饰的FD_TEMP_DIST(64位Windows仅有一种调用约定,无名字修饰后缀)。

  3. 逻辑参数的潜在类型不匹配
    Fortran代码中声明的LOGICAL(4) FLAG是4字节布尔类型,但VB.net用Byte(1字节)适配成功,说明Fortran库导出时将该参数转换成了单字节类型。Rust中用BYTE是正确的,但如果后续仍有问题,可尝试改用i32类型匹配Fortran的LOGICAL(4)。

修正后的Rust代码

use libloading::{library_filename, Library, Symbol};
use std::result::Result;
use winapi::shared::minwindef::BYTE;

// 替换为你的库文件名(不含后缀)
const MODULE: &str = "your_library_name";

pub fn fd_temp_dist(
    power: f64,
    mut array: Vec<f64>,
    length: i32,
    init_value_a: f64,
    init_value_b: f64,
    flag: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    // 先验证数组长度与传入的length一致,避免Fortran越界
    if array.len() != length as usize {
        return Err("Array length does not match LENGTH parameter".into());
    }

    // 修正函数签名:数组参数用*mut f64(单指针)
    type FdTempDistFunc = unsafe extern "stdcall" fn(
        *const f64,    // POWER: 传const指针,对应Fortran的传引用
        *mut f64,      // ARRAY: 数组首指针
        *const i32,    // LENGTH: 传const指针
        *const f64,    // INIT_VALUEA
        *const f64,    // INIT_VALUEB
        *const BYTE,   // FLAG
    );

    unsafe {
        let library = Library::new(library_filename(MODULE))?;
        // 根据平台选择正确的函数名:64位用b"FD_TEMP_DIST",32位用b"_FD_TEMP_DIST@24"
        let func: Symbol<FdTempDistFunc> = library.get(b"FD_TEMP_DIST")?;
        
        let flag_byte = if flag { 1_u8 } else { 0_u8 };
        func(
            &power,
            array.as_mut_ptr(),
            &length,
            &init_value_a,
            &init_value_b,
            &flag_byte,
        );
        Ok(())
    }
}

额外验证步骤

  1. 用dumpbin /exports your_library.dll(Windows)或nm -D your_library.so(Linux)查看库的导出函数名,确认你使用的函数名完全匹配。
  2. 确保传入的Vec<f64>长度严格等于length,避免Fortran访问数组时越界。

内容的提问来源于stack exchange,提问作者GreyAerin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:06:00