为啥我的 FFI 函数的第二次调用无法匹配字符串比较?
Posted
技术标签:
【中文标题】为啥我的 FFI 函数的第二次调用无法匹配字符串比较?【英文标题】: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");
【问题讨论】:
【参考方案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;
另见:
What's the difference between &mut unsafe and unsafe &mut ? Is there a builtin identity function in Rust? Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time Stuff the Identity Function Does (in Rust)【讨论】:
以上是关于为啥我的 FFI 函数的第二次调用无法匹配字符串比较?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Rust 函数和 FFI C++ 函数以相反的顺序执行?