首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Rust中包装一个(动态链接的)C库:使用rustc,而不是使用货物。

在Rust中包装一个(动态链接的)C库:使用rustc,而不是使用货物。
EN

Stack Overflow用户
提问于 2021-12-28 12:34:29
回答 1查看 981关注 0票数 2

对于我的项目,我需要能够运行一个预先编译成共享库的C函数。我在Ubuntu 20.10上做这个。我可以成功地使用锈蚀,但不是当我使用货物。

以下是我的文件列表(内容如下):

  • Cargo.toml
  • build.rs
  • include/test.h
  • src/test.c
  • src/lib.rs
  • src/main.rs

Cargo.toml

代码语言:javascript
复制
[package]
name = "libtest-sys"
version = "0.1.0"
links = "test"
build = "build.rs"
edition = "2021"

[dependencies]
libc = "0.2"

[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
pkg-config = "0.3"

build.rs

代码语言:javascript
复制
fn main() {
  println!("cargo:rustc-link-search={}", "/home/lanctot/rust_test");
  println!("cargo:rustc-link-lib=dylib=test");
}

test.h

代码语言:javascript
复制
void test();

test.c

代码语言:javascript
复制
#include <stdio.h>

void test() {
  printf("This is a test!\n");
}

lib.rs

代码语言:javascript
复制
include!("./bindings.rs");

main.rs

代码语言:javascript
复制
include!("./bindings.rs");

fn main() {
  unsafe {
    test();
  }
}

下面是我如何使用rustc生成共享库、锈蚀绑定和测试程序的方法:

代码语言:javascript
复制
$ pwd 
/home/lanctot/rust_test
$ gcc -c -fpic -Iinclude src/test.c -shared -o libtest.so
$ bindgen include/test.h -o src/bindings.rs
$ cat src/bindings.rs
/* automatically generated by rust-bindgen 0.59.2 */

extern "C" {
    pub fn test();
}
$ rustc -L. -ltest src/main.rs
$ ./main
This is a test!

太好了,它跑了!但是,当我尝试处理货物时:

代码语言:javascript
复制
$ cargo build --verbose
       Fresh pkg-config 3.24
       Fresh libc v0.2.112
       Fresh jobserver v0.1.24
       Fresh cc v1.0.72
   Compiling libtest-sys v0.1.0 (/home/lanctot/rust_test)
     Running `rustc --crate-name libtest_sys --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=fb122eefc998dd8f -C extra-filename=-fb122eefc998dd8f --out-dir /home/lanctot/rust_test/target/debug/deps -C incremental=/home/lanctot/rust_test/target/debug/incremental -L dependency=/home/lanctot/rust_test/target/debug/deps --extern libc=/home/lanctot/rust_test/target/debug/deps/liblibc-315c8c30d4535204.rlib --extern libtest_sys=/home/lanctot/rust_test/target/debug/deps/liblibtest_sys-13ba9453242dae24.rlib -L /home/lanctot/rust_test`
error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-Wl,--as-needed" "-L" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.0.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.1.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.2.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.3.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.4.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.5.rcgu.o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.6.rcgu.o" "-o" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f" "/home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.4257t6mbhq03i5nc.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/lanctot/rust_test/target/debug/deps" "-L" "/home/lanctot/rust_test" "-L" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-522c175df7e65c76.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-6de0d9a99fa442f6.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-acc51f402ffb0a47.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-cbf21249c0bb64a3.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-7811673bd6c230a1.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-9d24c50c56b501a5.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-f2bf86d8579f7abb.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-a510913c7a93022a.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-113eb81ce98dbb76.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-36a8ba3e35050b5b.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-6ec306849e1e0cbe.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-cb42b322cd006390.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-598bd3c8385c4a71.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-dcf076dc617ac8b6.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-9231e3c18aac66ef.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-fb02ea9686597718.rlib" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-f203df3b7c648201.rlib" "-Wl,--end-group" "/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-b0414f7c79a0b9b4.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc"
  = note: /usr/bin/ld: /home/lanctot/rust_test/target/debug/deps/libtest_sys-fb122eefc998dd8f.libtest_sys.57433ps7-cgu.0.rcgu.o: in function `libtest_sys::main':
          /home/lanctot/rust_test/src/main.rs:5: undefined reference to `test'
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: could not compile `libtest-sys`

Caused by:
  process didn't exit successfully: `rustc --crate-name libtest_sys --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=fb122eefc998dd8f -C extra-filename=-fb122eefc998dd8f --out-dir /home/lanctot/rust_test/target/debug/deps -C incremental=/home/lanctot/rust_test/target/debug/incremental -L dependency=/home/lanctot/rust_test/target/debug/deps --extern libc=/home/lanctot/rust_test/target/debug/deps/liblibc-315c8c30d4535204.rlib --extern libtest_sys=/home/lanctot/rust_test/target/debug/deps/liblibtest_sys-13ba9453242dae24.rlib -L /home/lanctot/rust_test` (exit status: 1)

我试过很多方法来解决这个问题。如果我删除main.rs,它就能工作。还要注意:我在上面的命令中没有看到所需的-ltest。我已经浏览了很多文档页面,并且相信所有的设置都是正确的。由于它可以很好地处理锈蚀,我相信不知何故,我缺少的是如何指示货物实际通过链接标志。

EN

回答 1

Stack Overflow用户

发布于 2021-12-28 14:20:13

来自货物簿

-l标志只传递给包的库目标,除非没有库目标,在这种情况下,它被传递给所有目标。这是因为所有其他目标都有对库目标的隐式依赖,并且给定的要链接的库应该只包含一次。这意味着如果包同时具有库和二进制目标,库可以访问给定库中的符号,而二进制程序应该通过库目标的公共API访问它们。

实际上,您的包有lib和bin:src/lib.rssrc/main.rs

如书所述,解决方案是,不要在二进制文件中使用C符号,而只在库中使用C符号。其基本原理是,当一个机箱同时有lib和bin时,库被认为是主要的部分(只有一个,当用作依赖项时使用),而bin是一个助手。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70507167

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档