I have a project with two files:
src/lib.rs
src/rle.rs
rle.rs
contains the following (and much more):
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
looks like the following:
mod rle;
use rle::rle_new;
// blablabla
When I load the library in Python I get the error:
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
It seems like Rust understands this (clever, clever) because my linter says:
17 1 warning function rle_new is marked #[no_mangle], but not exported, #[warn(private_no_mangle_fns)] on by default (rust-cargo)
How do I fix this and make my function rle_new
available from the target/debug/libranges.dylib file?
The crate-type
in my Cargo.toml
is ["dylib"]
The Rust philosophy is to prefer explicit over implicit.
Rust will only export symbols that are publicly accessible from the root crate. This makes it very easy to inspect the public interface of a crate without crawling through all files: just follow the pub
from the root.
In your case, the symbol rle_new
is publicly accessible to anyone having access to the rle
module (such as sibling modules), but the rle
module itself is not publicly accessible in the root crate.
The simplest solution is to selectively export this symbol:
pub use rle::rle_new;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With