为什么使用 libc 会阻止 cargo 正确链接我的程序?

Why does use libc stop cargo from linking my program correctly?

我有一些 C 代码,我编译成一个 .so 文件,我想从 Rust 程序中调用它。

// hello.c

void greet() {
    printf("Hello, world");
}

所以我将它编译成一个共享对象文件并将其添加到我的 build.rs 并且它工作正常

// main.rs

#[link(name = "hello")]
extern "C" {
    fn greet();
}

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

问题是我的 C 代码中有第二个函数,它接受 char* 作为参数,所以我尝试使用 libc::c_char 在 C 和 Rust 之间进行通信,但是每当我的程序没有' 当我导入 libc.

时编译
// main.rs

#[link(name = "hello")]
use libc::c_char;
extern "C" {
    greet();
}

而且我已经尝试只使用 import libc 进行编译(因为我认为这可能是问题所在)但它运行得很好所以似乎程序只有在我使用我的时才无法编译C 共享对象并导入 libc crate。

这是错误信息

error: linking with `cc` failed: exit code: 1
= note: "cc" 

  = note: Undefined symbols for architecture x86_64:
            "_greet", referenced from:
                project::main::h501a37fa09c5db9f in project.2q2eogqn7p5k3u7s.rcgu.o
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

对我来说工作得很好,你确定你编译了一个 Rust linker 可以使用的静态库,而不管其他什么被 link 编辑到最终的可执行文件中?

我只能猜测这有什么问题,因为你没有提供你是如何设置你的项目的,我建议让 cc crate 为你处理它,如果你真的需要什么它没有,为它做贡献,而不是手动编译 C 代码并尝试 link 它。


例子

build.rs

fn main() {
    cc::Build::new()
        .file("src/hello.c")
        .compile("hello");
}

src/hello.c

#include <stdio.h>

void greet() {
    printf("Hello, world\n");
}

src/main.rs

use libc::c_char;

#[link(name = "hello")]
extern "C" {
    fn greet();
}

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

cli

$ cargo run
   Compiling link v0.1.0 (~/Desktop/link)
warning: unused import: `libc::c_char`
 --> src/main.rs:4:5
  |
4 | use libc::c_char;
  |     ^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: 1 warning emitted

    Finished dev [unoptimized + debuginfo] target(s) in 0.50s
     Running `~/.cargo/target/debug/link`
Hello, world

#[link] 属性必须在 extern 块之前。通过在 #[link] 属性和 extern 块之间插入 use#[link] 属性附加到 use 并且没有任何效果。 (真的应该对此发出警告......)