如何在 Rust 中使用已编译的 C .so 文件
How to use a compiled C .so file in rust
has updated because of some suggestions
系统:macOS 10.14.6
这里想问的问题是如何使用rust调用编译好的.so文件,不好意思,我是新手。
我有一个非常简单的c文件:
#include "add.h"
int add(int a, int b) {
return a + b;
}
然后我用gcc-fPIC -shared -o libadd.so add.c
编译成.so文件放到lib目录下
然后我在 rust 的 build.rs 文件中写了这个:
use std::env;
use std::path::{Path};
fn main() {
let pwd_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let path = Path::new(&*pwd_dir).join("lib");
println!("cargo:rustc-link-search=native={}", path.to_str().unwrap());
println!("cargo:rustc-link-lib=dylib=add");
// println!("cargo:rustc-link-lib=static=add");
// println!("cargo:rerun-if-changed=src/hello.c");
}
我希望我能得到并使用这个功能,main.rs是:
extern { fn add(a: i32, b: i32) -> i32; }
fn main() {
let c = unsafe { let d = add(3, 5); d };
println!("c: {:?}", c);
}
cargo build
可以,但是 cargo run
有错误:
Compiling hello-from-generated-code-3 v0.1.0 (/Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3)
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
Running `target/debug/hello-from-generated-code-3`
dyld: Library not loaded: libadd.so
Referenced from: /Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3/target/debug/hello-from-generated-code-3
Reason: image not found
[1] 81811 abort cargo run
其他:我将 .so 更改为 .a 并且 cargo 运行 没问题。
示例代码here
感谢您的帮助!
我运行陷入同样的问题。 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
...
这是因为在 LD_LIBRARY_PATH
中找不到您的 .so 文件。您可以通过将库复制到相关文件夹或在 运行 您的程序时设置它来解决此问题。例如,您应该可以说:
LD_LIBRARY_PATH=. cargo run
(或您的 .so 文件所在的任何其他路径 - 不一定 .
)
我根本没有使用环境变量。例如你有 /your-crate/lib/libmystuff.so 共享库。为了 link 它,请指定以下内容:
println!("cargo:rustc-link-search=native=./lib");
println!("cargo:rustc-link-lib=dylib=mystuff");
注意,没有lib前缀的库,路径是相对的。
以防万一。您还可以使用头文件定义包含文件夹:
let headers = Path::new("/headers");
cc::Build::new()
.file("src/foo.c")
.include(headers)
.compile("foo");
已在 Linux 上测试。最好的问候。
has updated because of some suggestions
系统:macOS 10.14.6
这里想问的问题是如何使用rust调用编译好的.so文件,不好意思,我是新手。
我有一个非常简单的c文件:
#include "add.h"
int add(int a, int b) {
return a + b;
}
然后我用gcc-fPIC -shared -o libadd.so add.c
编译成.so文件放到lib目录下
然后我在 rust 的 build.rs 文件中写了这个:
use std::env;
use std::path::{Path};
fn main() {
let pwd_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let path = Path::new(&*pwd_dir).join("lib");
println!("cargo:rustc-link-search=native={}", path.to_str().unwrap());
println!("cargo:rustc-link-lib=dylib=add");
// println!("cargo:rustc-link-lib=static=add");
// println!("cargo:rerun-if-changed=src/hello.c");
}
我希望我能得到并使用这个功能,main.rs是:
extern { fn add(a: i32, b: i32) -> i32; }
fn main() {
let c = unsafe { let d = add(3, 5); d };
println!("c: {:?}", c);
}
cargo build
可以,但是 cargo run
有错误:
Compiling hello-from-generated-code-3 v0.1.0 (/Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3)
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
Running `target/debug/hello-from-generated-code-3`
dyld: Library not loaded: libadd.so
Referenced from: /Users/niexiaotao/work/rust-server/rust-ffi/hello-from-generated-code-3/target/debug/hello-from-generated-code-3
Reason: image not found
[1] 81811 abort cargo run
其他:我将 .so 更改为 .a 并且 cargo 运行 没问题。
示例代码here
感谢您的帮助!
我运行陷入同样的问题。 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
...
这是因为在 LD_LIBRARY_PATH
中找不到您的 .so 文件。您可以通过将库复制到相关文件夹或在 运行 您的程序时设置它来解决此问题。例如,您应该可以说:
LD_LIBRARY_PATH=. cargo run
(或您的 .so 文件所在的任何其他路径 - 不一定 .
)
我根本没有使用环境变量。例如你有 /your-crate/lib/libmystuff.so 共享库。为了 link 它,请指定以下内容:
println!("cargo:rustc-link-search=native=./lib");
println!("cargo:rustc-link-lib=dylib=mystuff");
注意,没有lib前缀的库,路径是相对的。 以防万一。您还可以使用头文件定义包含文件夹:
let headers = Path::new("/headers");
cc::Build::new()
.file("src/foo.c")
.include(headers)
.compile("foo");
已在 Linux 上测试。最好的问候。