代码之家  ›  专栏  ›  技术社区  ›  Ross MacArthur

如何将库链接到C代码并在Rust二进制文件中使用它?

  •  1
  • Ross MacArthur  · 技术社区  · 6 年前

    我正试图在我的Rust项目中包含一个C文件。C文件使用系统依赖项。下面是一个在我运行 cargo build .

    如果我接受了Cargo正在运行的失败命令 "-l" "nl-genl-3" "-l" "nl-3" 命令 成功。是不是把链接器标志放错了地方,因为这些标志肯定 在指挥部?

    src/主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;
    }
    

    建设资源

    extern crate cc;
    
    fn main() {
        cc::Build::new()
            .include("/usr/include/libnl3")
            .file("src/nl.c")
            .compile("libnl.a");
    }
    

    货物.toml

    [package]
    name = "derp"
    version = "0.1.0"
    
    [build-dependencies]
    cc = "1.0"
    

    运行时得到以下输出 货物建造

       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
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Shepmaster Tim Diekmann    6 年前

    Cargo documentation for build scripts :

    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");
    

    并移除 link 从你的锈代码属性。


    问题是链接器标志指出Rust代码需要链接到C库,但这并不是完全正确的。你的 C代码 需要链接到库,而Rust代码需要链接到编译的C代码。如果您查看这些参数,就会看到这个(节略的)输出

    • deps/derp-5a7445c256565e2d.1vmrdj4gsxr690x4.rcgu.o (你的铁锈代码)
    • -l nl-genl-3 (系统库)
    • -l nl-3 (系统库)
    • -l nl (您的C垫片)

    链接器的参数顺序很重要。如果链接器处理对象时不需要什么, 不会用的 .

    在这里,Rust代码添加了对 nl 库,所以链接器正在查找这些符号。什么时候? nl-3 nl-genl-3 是经过处理的,我们不需要它们的任何符号,所以它们大多被忽略。什么时候? 新加坡国立大学 处理后,我们从Rust代码中解析依赖关系,但是 新加坡国立大学 需要来自的符号 nl-genl-3型 nl-3号 ,将不再处理。

    不明显,但是 compile 方法来自 cc 自动打印出 cargo:rustc-link-lib 将其生成结果绑定到锈代码中。

    另见: