如何在 Rust 中使用编译好的 C .so 文件

聂小涛*_*聂小涛 7 c shared-libraries rust

\n

由于一些建议而更新

\n
\n\n
\n\n

系统\xef\xbc\x9amacOS 10.14.6

\n\n

这里我想问的问题是如何使用rust调用编译好的.so文件,抱歉,我对这部分是新手。

\n\n

我有一个非常简单的 c 文件:

\n\n
#include "add.h"\n\nint add(int a, int b) {\n    return a + b;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我习惯gcc-fPIC -shared -o libadd.so add.c编译成.so文件放到lib目录下

\n\n

然后我在 rust 的 build.rs 文件中写入了以下内容:

\n\n
\nuse std::env;\nuse std::path::{Path};\n\nfn main() {\n    let pwd_dir = env::var("CARGO_MANIFEST_DIR").unwrap();\n    let path = Path::new(&*pwd_dir).join("lib");\n    println!("cargo:rustc-link-search=native={}", path.to_str().unwrap());\n    println!("cargo:rustc-link-lib=dylib=add");\n    // println!("cargo:rustc-link-lib=static=add");\n    // println!("cargo:rerun-if-changed=src/hello.c");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望我可以得到并使用这个函数,main.rs 是:

\n\n
extern { fn add(a: i32, b: i32) -> i32; }\n\nfn main() {\n    let c = unsafe { let d = add(3, 5); d };\n    println!("c: {:?}", c);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

cargo build没问题,但是cargo run有错误:

\n\n
   Compiling hello-from-generated-code-3 v0.1.0 (/Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3)\n    Finished dev [unoptimized + debuginfo] target(s) in 0.34s\n     Running `target/debug/hello-from-generated-code-3`\ndyld: Library not loaded: libadd.so\n  Referenced from: /Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3/target/debug/hello-from-generated-code-3\n  Reason: image not found\n[1]    81811 abort      cargo run\n
Run Code Online (Sandbox Code Playgroud)\n\n

其他事情:我将 .so 更改为 .a 并且货物运行正常。

\n\n

示例代码在这里

\n\n

感谢您的帮助!

\n

use*_*321 3

我遇到了同样的问题。Cargo 似乎可以正确构建您的库,因为您明确告诉它在哪里查找文件(使用rustc-link-search)。然而,当你去运行它时,Linux并不知道它在哪里。

如果您要ldd在编译后的 Rust 二进制文件上运行,您会得到如下结果:

$ ldd target/debug/hello-from-generated-code-3
        linux-vdso.so.1 (0xabcd)
        libadd.so => not found      <----- ldd can't find your library
        ...
Run Code Online (Sandbox Code Playgroud)

这是因为在 中找不到您的 .so 文件LD_LIBRARY_PATH。您可以通过将库复制到相关文件夹中或仅在运行程序时进行设置来解决此问题。例如,你应该能够说:

LD_LIBRARY_PATH=. cargo run
Run Code Online (Sandbox Code Playgroud)

(或者 .so 文件所在的任何其他路径 - 不一定.