Этот код показывает FFI от Rust до Fortran, потому что именно там я заметил проблему, но я уверен, что это не специфично для 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");
}