функция помечена #[no_mangle], но не экспортирована

#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;