为什么第二次调用FFI函数无法匹配字符串比较?

时间:2019-07-02 00:21:33

标签: rust ffi unsafe

此代码显示了从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在cc = "1.0"中有[build-dependencies],并且我有以下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");
}

1 个答案:

答案 0 :(得分:4)

这里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;
}

另请参阅: