使用 FFI 链接到 Rust 的本地 C 库

Chr*_*isR 7 c linker ffi rust

我正在尝试用Rust包装一个相当大的 C 库。我使用bindgen 来生成绑定。Rust 似乎对这些感到满意。然而,尽管我进行了不同的尝试并且多次阅读了构建脚本文档,但我仍然遇到链接问题。

\n\n

我正在使用的库有一组 csh 脚本,最终会构建两个.a文件:cspice.acsupport.a. 它们都存储在cspice_linux_gcc_64bit/lib我的项目中(参见底部的树)。

\n\n

我目前通过调用测试中的常量和函数来测试正确的绑定,参见。库文件(在我的 Github 上)。

\n\n

build.rs我高度怀疑我的或者不太可能是我的有问题Cargo.toml

\n\n

链接错误

\n\n
Running `rustc --crate-name spice src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=94c06ffe4bfd7d5f -C extra-filename=-94c06ffe4bfd7d5f --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice`\n\nerror: could not find native static library `cspice`, perhaps an -L flag is missing?\n\nerror: Could not compile `spice`.\n\nCaused by:\n  process didn\'t exit successfully: `rustc --crate-name spice src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=94c06ffe4bfd7d5f -C extra-filename=-94c06ffe4bfd7d5f --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice` (exit code: 101)\nBuild failed, waiting for other jobs to finish...\nerror: linking with `cc` failed: exit code: 1\n  |\n  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/chris/Workspace/rust/SPICE/target/debug/deps/spice-e22b64d176595306.0.o" "-o" "/home/chris/Workspace/rust/SPICE/target/debug/deps/spice-e22b64d176595306" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "/home/chris/Workspace/rust/SPICE/target/debug/deps" "-L" "cspice_linux_gcc_64bit/lib" "-L" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "cspice" "-Wl,--no-whole-archive" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-163c20e386ec0612.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-bd312ea730ea22d0.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-4959b4e709084e0a.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-fb44afc024bbc636.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-14b8f3202acdad6a.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-20a50a22d4c2b1e9.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-b479831207997444.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-10b591f1a68dd370.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-28913dc5a1e63cd7.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-6ecacccb5bdc4911.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_unicode-f4f0ae88f5ad8ad4.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-bfaa82017ca17cb2.rlib" "/home/chris/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-863b57a66ba6c3e1.rlib" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util"\n  = note: /usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: cannot find -lcspice\n          collect2: error: ld returned 1 exit status\n\n\nerror: aborting due to previous error(s)\n\nerror: Could not compile `spice`.\n\nCaused by:\n  process didn\'t exit successfully: `rustc --crate-name spice src/lib.rs --emit=dep-info,link -C debuginfo=2 --test -C metadata=e22b64d176595306 -C extra-filename=-e22b64d176595306 --out-dir /home/chris/Workspace/rust/SPICE/target/debug/deps -L dependency=/home/chris/Workspace/rust/SPICE/target/debug/deps -L native=cspice_linux_gcc_64bit/lib -l static=cspice` (exit code: 101)\n
Run Code Online (Sandbox Code Playgroud)\n\n

build.rs

\n\n
extern crate bindgen;\n\nuse std::env;\nuse std::path::PathBuf;\n\n\nfn main() {\n    let out_dir = env::var("OUT_DIR").unwrap();\n    // Tell cargo to tell rustc to link the system bzip2\n    // shared library.\n    println!("cargo:rustc-link-search=native=cspice_linux_gcc_64bit/lib");\n    println!("cargo:rustc-link-lib=static=cspice");\n    //println!("cargo:rustc-flags=-L cspice_linux_gcc_64bit/lib");\n\n    // The bindgen::Builder is the main entry point\n    // to bindgen, and lets you build up options for\n    // the resulting bindings.\n    let bindings = bindgen::Builder::default()\n        // The input header we would like to generate\n        // bindings for.\n        .header("spice_wrapper.h")\n        // Finish the builder and generate the bindings.\n        .generate()\n        // Unwrap the Result and panic on failure.\n        .expect("Unable to generate bindings");\n\n\n    let out_path = PathBuf::from(out_dir.clone());\n    // Write the bindings to the $OUT_DIR/bindings.rs file.\n    bindings\n        .write_to_file(out_path.join("spice_bindings.rs"))\n        .expect("Couldn\'t write bindings!");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

Cargo.toml

\n\n
extern crate bindgen;\n\nuse std::env;\nuse std::path::PathBuf;\n\n\nfn main() {\n    let out_dir = env::var("OUT_DIR").unwrap();\n    // Tell cargo to tell rustc to link the system bzip2\n    // shared library.\n    println!("cargo:rustc-link-search=native=cspice_linux_gcc_64bit/lib");\n    println!("cargo:rustc-link-lib=static=cspice");\n    //println!("cargo:rustc-flags=-L cspice_linux_gcc_64bit/lib");\n\n    // The bindgen::Builder is the main entry point\n    // to bindgen, and lets you build up options for\n    // the resulting bindings.\n    let bindings = bindgen::Builder::default()\n        // The input header we would like to generate\n        // bindings for.\n        .header("spice_wrapper.h")\n        // Finish the builder and generate the bindings.\n        .generate()\n        // Unwrap the Result and panic on failure.\n        .expect("Unable to generate bindings");\n\n\n    let out_path = PathBuf::from(out_dir.clone());\n    // Write the bindings to the $OUT_DIR/bindings.rs file.\n    bindings\n        .write_to_file(out_path.join("spice_bindings.rs"))\n        .expect("Couldn\'t write bindings!");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
[package]\n(...)\nlinks = "cspice"\nbuild = "build.rs"\n\n[build-dependencies]\nbindgen = "0.26.3"\n\n[dependencies]\n
Run Code Online (Sandbox Code Playgroud)\n

She*_*ter 5

构建两个 .a 文件:cspice.acsupport.a

在 Linux 上,静态库通常称为libfoo.a,但您的库没有lib前缀。

将文件重命名为libcspice.a应该允许其编译。我不确定您是否想要修改构建脚本或库构建脚本来执行重命名。库本身甚至可能有一个编译开关来使用平台标准命名方案。