【问题标题】:How to pass 2D Vector from Rust to Fortran with FFI?如何使用 FFI 将 2D 矢量从 Rust 传递到 Fortran?
【发布时间】:2020-10-06 18:36:51
【问题描述】:

我正在尝试将 2D f64 向量 (Vec) 从 Rust 传递给 Fortran 函数。我一直在使用 .as_mut_ptr() 将一维向量与其他 Fortran 函数一起使用。

我不完全确定如何为这样的事情发布一个最小的工作示例,但我们开始吧:

extern "C" {
    fn fortran1_(
        vector: *mut f64,
        length1: *const uint32_t
    );

    fn fortran2_(
        vector: *mut f64, 
        length1: *const uint32_t, 
        length2: *const uint32_t
    );
}

pub fn fortran1(
    length1: u32
) -> Vec<f64>{
    let mut vector = vec![0_f64; length1];
    unsafe{
        fortran1_(
            vector.as_mut_ptr(),
            &length1)
    }
    return vector;
}

pub fn fortran2(
    length1: u32, 
    length2: u32
)-> Vec<Vec<f64>>{
    let mut vector = vec![vec![0_f64; length1]; length2];
    unsafe{
        fortran2_(vector.as_mut_ptr(), 
        &length1, 
        &length2)
    }
    return vector;
}

谢谢

【问题讨论】:

  • 我强烈建议使用一维数组,并使用它是多维的,或者使用ndarray libraryVec 不会内联存储其元素,这意味着虽然来自每个内部数组的数据 是连续的,但内部数组彼此不连续。换句话说,您无法通过索引或指针算术获得第二个向量,因为没有一致的步幅模式。

标签: rust fortran ffi


【解决方案1】:

您的 rust Vec&lt;Vec&lt;_&gt;&gt; 表示与 Fortran 的标准数据模型之间存在大量不匹配。

Fortran 期望二维数组布局在f64 的连续切片中,但Vec&lt;Vec&lt;_&gt;&gt; 将其每一行放入单独的堆分配中。

Fortran 索引是从 1 开始的,但 Vec 是从 0 开始的。

您最好实现 struct Fortran2d&lt;T&gt; { vec: Vec&lt;T&gt;, rows: usize, cols:usize, } 并在该模拟 Fortran 索引上实现方法。我认为那将是最不痛苦的。

impl Fortran2d<T> {
    /// maps fortran style 2d index to internal vec index
    fn index(&self, c: usize, r: usize) -> usize {
        assert!(c > 0 && c <= self.cols);
        assert!(r > 0 && r <= self.rows);
        (c - 1) + (r - 1) * self.cols
   }
}

【讨论】:

  • Nit: "Fortran 索引是从 1 开始的" ... 默认是从 1 开始的,但是 Fortran 允许您使用任何您想要的整数基数。
猜你喜欢
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2019-12-28
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 2018-10-15
相关资源
最近更新 更多