函数被标记为#[no_mangle],但未导出。

8

我有一个包含两个文件的项目:

  • 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_newtarget/debug/libranges.dylib 文件中可用?

在我的 Cargo.toml 中,crate-type["dylib"]


1
翻译: 猜测一下:在lib.rs中使用pub use rle::rle_new;?(rle不是pub...) - Matthieu M.
我尝试过了,但没有起作用。我还尝试将 mod rle 更改为 pub mod rle,但也没有起作用。无论如何,还是谢谢 :) - The Unfun Cat
嗯,最简单的方法是将我的 rle_new 函数移动到 lib.rs 文件中。然后就可以工作了 :) 保持这个状态开放,以防有人有答案。 - The Unfun Cat
按照@MatthieuM.的建议(pub use)操作,使_rle_new在库中以导出符号的形式出现,如nm所示。对我有用。 - Shepmaster
@Shepmaster:以前缀“_”开头?如果是这种情况,我会让你回答并填写空白处,似乎符号名称被更改很奇怪... - Matthieu M.
显示剩余5条评论
1个回答

17

Rust的哲学是更喜欢显式而不是隐式。

Rust只会导出从根模块(public root)可以公开访问的符号。这使得检查一个crate的公共接口变得非常容易,无需遍历所有文件:只需从根模块(public root)遵循pub即可。

在您的情况下,符号rle_new对于任何可以访问rle模块(如兄弟模块)的人都是公开访问的,但rle模块本身在根模块中是不公开访问的。

最简单的解决方案是有选择地导出此符号:

pub use rle::rle_new;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接