У меня есть библиотека Rust (1.2), и я хочу использовать ее функции из Python (3.4), используя FFI Rust. Я на OSX 10.10 Йосемити.Как исправить ошибку сегментации при передаче массива int?
Почти все мои функции принимают изменяемую ссылку ломтика как вход:
pub fn myfunction<T>(array: &mut [T]) { ... }
Я тогда разоблачить эту функцию, чтобы использовать вне ржавчины с:
#[no_mangle]
pub extern fn ffi_myfunction(array_pointer: *const libc::int8_t, n: libc::size_t) {
assert!(!array_pointer.is_null());
assert!(n != 0);
let mut to_sort = unsafe {
slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
};
myfunction(&mut to_sort);
}
Это прекрасно работает: с помощью языка Python модуль ctypes я могу назвать ffi_myfunction()
с Numpy массива:
#!/usr/bin/env python3
import ctypes
import numpy as np
rustlib = ctypes.CDLL("target/debug/libmylib.dylib")
array = np.arange(5, dtype=np.int8)
rustlib.ffi_myfunction(ctypes.c_void_p(array.ctypes.data), len(array))
У меня также есть ржавая реализация с libc::int16_t
, libc::int32_t
и libc::int64_t
, и я могу назвать их np.int16
, np.int32
и np.int64
.
У меня есть второй набор функций Rust, которые я хочу вызвать из Python. Эти функции немного отличаются, поскольку они берут изменяемую ссылку на вектор (а не к ломтику):
pub fn myotherfunction<T>(array: &mut Vec<T>) { ... }
Затем я создаю мою обертку, как например:
#[no_mangle]
pub extern "C" fn ffi_myotherfunction(array_pointer: *const libc::int8_t, n: libc::size_t) {
assert!(!array_pointer.is_null());
assert!(n != 0);
let mut to_sort = unsafe {
Vec::from_raw_parts(array_pointer as *mut i8, n as usize, n as usize)
};
myotherfunction(&mut to_sort);
}
К сожалению, я получаю ошибку сегментации при вызов ffi_myotherfunction()
из Python.
После некоторого исследования, я могу сказать следующее:
- Добавление
println!()
макроса в любом месте либоmyotherfunction()
илиffi_myotherfunction()
сделать функцию, чтобы работать должным образом. Вывод будет таким, как ожидалось. - Использована библиотека ржавчины segfaults для любого используемого целого размера (целые числа 8, 16, 32 и 64 бита).
- Segfault, похоже, не от
myotherfunction()
, а от звонка доVec::from_raw_parts()
. Например, я могу прокомментировать звонокmyotherfunction()
отffi_myotherfunction()
, оставив только небезопасный блок, и segfault все еще происходит.
Таким образом, существует разница между slice::from_raw_parts_mut()
и Vec::from_raw_parts()
.
Но я не могу понять, что вызывает этот segfault. Я что-то упускаю? Я делаю что-то неправильно? Может ли быть проблема с тем, как numpy хранит свои данные? Или, может быть, что-то о жизни, заимствованиях или каких-либо других понятиях ржавчины, которые я не получаю?
Спасибо!
Так что я должен использовать 'slice :: from_raw_parts_mut()' вместо 'Vec :: from_raw_parts()', это что? –
@big_gie: действительно. –