【问题标题】:Why does the second call to my FFI function fail to match the string comparison?为什么我的 FFI 函数的第二次调用无法匹配字符串比较?
【发布时间】:2019-07-02 00:21:33
【问题描述】:

这段代码显示了从 Rust 到 Fortran 的 FFI,因为这是我注意到问题的地方,但我很确定这不是 Fortran 特定的,甚至可能与 FFI 无关。

我有 src/main.rs,一个相当小的东西:

extern crate libc;

extern "C" {
    static mut __wrapper_mod_MOD_a_string: [libc::c_char; 30];
    fn __wrapper_mod_MOD_say_hi();
}

fn main() {
    let s = String::from("hello");
    unsafe { __wrapper_mod_MOD_say_hi() };

    for i in unsafe { __wrapper_mod_MOD_a_string.iter_mut() } {
        *i = ' ' as libc::c_char;
    }

    for (i, c) in unsafe { __wrapper_mod_MOD_a_string }.iter_mut().zip(s.chars()) {
        *i = c as libc::c_char;
    }

    unsafe { __wrapper_mod_MOD_say_hi() };

    for (i, c) in unsafe { __wrapper_mod_MOD_a_string.iter_mut().zip(s.chars()) } {
        *i = c as libc::c_char;
    }

    unsafe { __wrapper_mod_MOD_say_hi() };
}

这会调用 src/wrapper.f90:

module wrapper_mod
   implicit none

   private
   public :: say_hi
   character(30) :: a_string

contains

   subroutine say_hi
      if (trim(a_string) == 'hello') then
         write(6,*) 'Howdy there, partner'
      else
         write(6,*) 'Rude of you not to greet me'
      endif
   end subroutine say_hi
end module wrapper_mod

我得到了输出:

 Rude of you not to greet me
 Rude of you not to greet me
 Howdy there, partner

为什么?最后两行的唯一区别是unsafe 块的范围。我认为不安全的操作是通过 FFI 进行访问,但是一旦我有了一个数组,就可以随意迭代它应该是“安全的”。显然我误解了什么。

我的 Cargo.toml 在 [build-dependencies] 中有 cc = "1.0",并且我有以下 build.rs:

extern crate cc;

fn main() {
    cc::Build::new()
        .file("src/wrapper.f90")
        .compile("libwrapper.a");
    println!("cargo:rustc-link-lib=static=wrapper");
    println!("cargo:rustc-link-lib=dylib=gfortran");
}

【问题讨论】:

    标签: rust ffi unsafe


    【解决方案1】:

    这里使用unsafe 没有什么特别之处。普通花括号也会发生同样的事情:

    fn main() {
        let mut bytes = [0; 4];
        let new_bytes = b"demo";
    
        for (i, &c) in { bytes }.iter_mut().zip(new_bytes) {
            *i = c;
        }
    
        println!("{:?}", bytes);
        // [0, 0, 0, 0]
    
        for (i, &c) in { bytes.iter_mut().zip(new_bytes) } {
            *i = c;
        }
    
        println!("{:?}", bytes);
        // [100, 101, 109, 111]
    }
    

    使用大括号会强制在大括号内移动变量。由于[libc::c_char; 30][u8; 4] 都实现了Copy,因此由于移动而进行了隐式复制。您可以获取可变引用并将其移动到花括号中:

    for (i, &c) in { &mut bytes }.iter_mut().zip(new_bytes) {
        *i = c;
    }
    

    另见:

    【讨论】:

      猜你喜欢
      • 2022-03-30
      • 2012-12-10
      • 2012-10-12
      • 2013-04-08
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 2012-02-09
      相关资源
      最近更新 更多