[英]How can I link both C and C++ code, along with C and C++ runtime libraries (including STL) on android ndk?
[英]How can I link libraries to my C code and use that in a Rust binary?
我正在尝试在我的 Rust 项目中包含一个 C 文件。 C 文件使用系统依赖项。 下面是一个在我运行cargo build
时不会编译的最小示例。
如果我执行 Cargo 正在运行的失败命令并附加"-l" "nl-genl-3" "-l" "nl-3"
该命令会成功。 难道把链接标志在错误的地方,因为这些标志肯定是在命令?
src/main.rs
#[link(name = "nl-genl-3")]
#[link(name = "nl-3")]
extern "C" {
fn nl_test(help_me_pls: usize) -> usize;
}
fn main() {
unsafe {
println!("nl.c function result: {:?}", nl_test(6));
}
}
src/nl.c
#include <linux/nl80211.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
int nl_test(int help_me_pls) {
struct nl_sock* socket = nl_socket_alloc();
nl_socket_free(socket);
return help_me_pls;
}
构建.rs
extern crate cc;
fn main() {
cc::Build::new()
.include("/usr/include/libnl3")
.file("src/nl.c")
.compile("libnl.a");
}
Cargo.toml
[package]
name = "derp"
version = "0.1.0"
[build-dependencies]
cc = "1.0"
当我运行cargo build
时,我得到以下输出
Compiling cc v1.0.18
Compiling derp v0.1.0 (file:///root/derp)
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.1vmrdj4gsxr690x4.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.1y16o1qfye96o7m0.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.3rngp6bm2u2q5z0y.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.4oc10dk278mpk1vy.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.4xq48u46a1pwiqn7.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.51s1w397y42gpez1.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.8xzrsc1ux72v29j.rcgu.o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.oa3rad818d8sgn4.rcgu.o" "-o" "/root/derp/target/debug/deps/derp-5a7445c256565e2d" "/root/derp/target/debug/deps/derp-5a7445c256565e2d.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/root/derp/target/debug/deps" "-L" "/root/derp/target/debug/build/derp-c3cdcf1fbd0c70b2/out" "-L" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "-l" "nl-genl-3" "-l" "nl-3" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "nl" "-Wl,--no-whole-archive" "-Wl,--start-group" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-774f1a5992f88ec5.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_unwind-a65ab1ab71045d14.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_jemalloc-5cced33d7a39db8e.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunwind-76fba694360269fc.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc_system-b3f660c2be971c37.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liblibc-64d840c62d40ace0.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc-b3d8b67c899d207d.rlib" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcore-d9124265921c5963.rlib" "-Wl,--end-group" "/root/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcompiler_builtins-1aad7d9a81def783.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util"
= note: /root/derp/target/debug/build/derp-c3cdcf1fbd0c70b2/out/libnl.a(nl.o): In function `nl_test':
/root/derp/src/nl.c:6: undefined reference to `nl_socket_alloc'
/root/derp/src/nl.c:7: undefined reference to `nl_socket_free'
collect2: error: ld returned 1 exit status
rustc-link-lib=[KIND=]NAME
表示指定的值是一个库名,应该作为-l
标志传递给编译器。 可选的KIND
可以是static
、dylib
(默认)或framework
,有关更多详细信息,请参阅rustc --help
。
将此添加到您的构建脚本中:
println!("cargo:rustc-link-lib=nl-genl-3");
println!("cargo:rustc-link-lib=nl-3");
并从 Rust 代码中删除link
属性。
问题是您的链接器标志表明 Rust 代码需要链接到 C 库,但这并不完全正确。 您的C 代码需要链接到库,而您的 Rust 代码需要链接到已编译的 C 代码。 如果你看一下参数,你会看到这个(删减的)输出
deps/derp-5a7445c256565e2d.1vmrdj4gsxr690x4.rcgu.o
(你的 Rust 代码)-l nl-genl-3
(系统库)-l nl-3
(系统库)-l nl
(你的 C 垫片)链接器的参数顺序很重要。 如果链接器处理对象时不需要某些东西,则不会使用它。
在这里,Rust 代码添加了对来自nl
库的代码的依赖,因此链接器正在寻找这些符号。 在处理nl-3
和nl-genl-3
,我们不需要它们中的任何符号,因此它们大多被忽略。 当nl
被处理时,我们从 Rust 代码中解析依赖,但是nl
需要来自nl-genl-3
和nl-3
的符号,它们不会被再次处理。
这并不明显,但是来自cc
的compile
方法会自动打印出一个cargo:rustc-link-lib
行,将其构建结果绑定到您的 Rust 代码中。
也可以看看:
这就是我解决它的方法Rust + .so lib 。 希望它会有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.