#rust
#Ржавчина
Вопрос:
У меня есть проект с двумя файлами:
src/lib.rs
src/rle.rs
rle.rs
содержит следующее (и многое другое):
extern crate libc;
#[derive(Debug, PartialEq)]
pub struct Rle {
pub lengths: Vec<i32>,
pub values: Vec<i32>,
}
#[no_mangle]
pub extern "C" fn rle_new(blablabla...)
lib.rs
выглядит следующим образом:
mod rle;
use rle::rle_new;
// blablabla
Когда я загружаю библиотеку в Python, я получаю сообщение об ошибке:
Traceback (most recent call last):
File "compact_ranges.py", line 19, in <module>
lib.rle_new.restype = POINTER(RleS)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 378, in __getattr__
func = self.__getitem__(name)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x7f94ca700370, rle_new): symbol not found
Похоже, что Rust понимает это (умный, сообразительный), потому что мой линтер говорит:
17 1 warning function rle_new is marked #[no_mangle], but not exported, #[warn(private_no_mangle_fns)] on by default (rust-cargo)
Как мне это исправить и сделать мою функцию rle_new
доступной из target / debug / libranges.файл dylib?
crate-type
В моем Cargo.toml
есть ["dylib"]
Комментарии:
1. Выстрел в темноте:
pub use rle::rle_new;
вlib.rs
? (rle
неpub
…)2. Я попробовал это, и это не сработало. Я также пытался изменить
mod rle
наpub mod rle
, но это тоже не сработало. В любом случае спасибо 🙂3. Возможно, потребуется открыть ошибку, чтобы улучшить предупреждение; было бы гораздо полезнее, если бы в нее был включен совет о том, как это исправить:(
4. Ну, самым простым способом было переместить мою
rle_new
функцию вlib.rs
файл. Тогда сработало 🙂 Оставляем это открытым как есть, на случай, если у sb есть ответ.5. Выполняю как @MatthieuM. предлагает (
pub use
), чтобы_rle_new
отображался как экспортированный символ в библиотеке в соответствии сnm
. Работает для меня.
Ответ №1:
Философия Rust заключается в том, чтобы предпочесть явное неявному.
Rust экспортирует только те символы, которые общедоступны из корневого ящика. Это упрощает проверку общедоступного интерфейса ящика без обхода всех файлов: просто следуйте pub
из корня.
В вашем случае символ rle_new
является общедоступным для всех, кто имеет доступ к rle
модулю (например, к родственным модулям), но rle
сам модуль не является общедоступным в корневом хранилище.
Самое простое решение — выборочно экспортировать этот символ:
pub use rle::rle_new;