Calling function from portable lib


#1

I generated a libfoo.dylib library file from Rust as below:

lib.rs:

#[no_mangle]
pub fn public_function() {
    println!("called rary's `public_function()`");
}

fn private_function() {
    println!("called rary's `private_function()`");
}

pub fn indirect_access() {
    print!("called rary's `indirect_access()`, that\n> ");

    private_function();
}

Cargo.toml:

[package]
name = "foo"
version = "0.1.0"
authors = ["Hasan Yousef"]

[lib]
name = "foo"
crate-type = ["dylib", "rlib"]
exactname = {dylib = "{}.so", rlib = "{}.rlib"}

[dependencies]

and by running cargo build I got the libfoo.dylib and libfoo.rlib files generated in the target folder.

I copied the 2 generated files above to a lib folder in another project, which have the below 2 files:

main.rs:

extern  crate  libfoo;
use libfoo::*;

fn main() {
    println!("Hello, my world!");

    public_function();
}

Cargo.toml:

[package]
name = "app"
version = "0.1.0"
authors = ["Hasan Yousef"]

[dependencies]
libfoo = { path = "./libs" }

Once running the cargo run I got the below error:

error: no matching package named libfoo found (required by app)
location searched: file:///Users/hasan/Documents/RUST/rustmac/app/libs
version required: *

What wrong thing I have above, and how to fix it?


#2
  1. I’m not sure what you mean by “portable lib,” but Rust dylibs are not at all portable. Maybe you’re looking for cdylib? Then you probably also want to use extern "C" on your public functions.

  2. The [dependencies] section in Cargo.toml is meant for source dependencies. With path = ... you are specifying a path to the source code of the crate you want to depend on. You can’t use it for binary dependencies. If you want to link to a cdylib, check out https://doc.rust-lang.org/book/first-edition/ffi.html


#3

Thanks @jethrogb but I did not understand anything :frowning:
By portable, I mean shared, a binary file that I can use in another app, same like .dd or .jar

I tried to understand the page you linked and wrote the below code but it give errors:

lib.rs:
extern crate libc;

#[no_mangle]
pub extern "C" fn public_function() {
    println!("called rary's `public_function()`");
}

fn private_function() {
    println!("called rary's `private_function()`");
}

pub fn indirect_access() {
    print!("called rary's `indirect_access()`, that\n> ");

    private_function();
}

Cargo.toml:

[package]
name = "foo"
version = "0.1.0"
authors = ["Hasan Yousef <hasan.oryx@gmail.com>"]

[dependencies]
libc = "0.2.0"

Upon running cargo build I got a file named libfoo.rlib for which I got the same error as in the initial question :frowning:


#4

Why are you adding the libc dependency? I think you want this:

[package]
name = "foo"

[lib]
crate-type = ["cdylib"]

#5

@jethrogb the generated one is: libfoo.dylib and ended up with same issues


#6

Your extern crate line should be extern crate foo; and not extern crate libfoo;

I recommend reading this http://doc.crates.io/guide.html also


#7

Note that all Cargo.toml dependencies must be Rust source packages. There is no way to include any .so/.dylib/.a/.rlib directly as a Cargo dependency.

  • If you’re just trying to use Rust code from another Rust project, then the dylib/cdylib path is most likely inappropriate and unnecessary complication. For linking Rust code you should “link” Cargo projects to Cargo projects.

  • If you’re trying to explicitly make a C-compatible shared library linked at run time, then you have to either write linker commands in a custom build.rs script, or add #[link(…)] extern "C" {} to your code.