nagisa / rust_libloading

Bindings around the platform's dynamic library loading primitives with greatly improved memory safety.
https://docs.rs/libloading
ISC License
1.24k stars 102 forks source link

`"symbol not found"` error #112

Closed ra0x3 closed 1 year ago

ra0x3 commented 1 year ago

Description

Error

thread 'main' panicked at 'bar: DlSym { desc: "dlsym(0x21d897740, foobar): symbol not found" }', bar/src/main.rs:4:83
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Minimum reproducible example

Project layout

.
├── Cargo.lock
├── Cargo.toml
├── bar
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── foo
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
        └── lib.rs

4 directories, 7 files

My fake library who's function I'd like to call

// foo/src/lib.rs
fn foobar() {
    println!("Hello world!");
}

My fake binary, in which I'm trying to load my foo library and call it's foobar function

// bar/src/main.rs
fn main() {
        unsafe {
            let lib = libloading::Library::new("/path/to/my/libfoo.dylib").expect("foo");
            let func: libloading::Symbol<unsafe extern fn()> = lib.get(b"foobar").expect("bar");
            func();
        }
}

Expected behavior

nagisa commented 1 year ago

Rust does not export functions by default (you need to make them public!) and it also mangles functions by default (see the no_mangle attribute – documentation references this problem here). You’re also missing extern for your function definition to make sure that the ABI matches on both sides. This chapter from nomicon might be helpful to you.

libfoo.dylib suggests me you’re on MacOS. You should be able to use the nm utility to list the symbols in your library. For a symbol to be importable, it’ll need to have a capital letter (indicating it is an exported global symbol) such as T on the 2nd column.

I strongly recommend seeking advice/help on the venues dedicated to helping Rustaceans – you will be able to get help much faster than from me on this issue tracker.