【发布时间】:2021-06-08 08:06:24
【问题描述】:
我一直在尝试在 windows 中编译一个简单的 rustcdylib crate 并将其与一个简单的 c 程序链接。尽管我付出了所有努力,我还是无法链接dll 文件。
小例子
首先我的rustc版本是:
C:\Users\User> rustc --version
rustc 1.50.0 (cb75ad5db 2021-02-10)
我有一个基本的Cargo.toml,其中包括一个cbindgen,并设置了箱子类型:
[package]
name = "mycrate"
version = "0.1.0"
authors = ["PauMAVA <--REDACTED-->"]
edition = "2018"
[lib]
name = "mycrate"
crate-type = ["cdylib"]
[build-dependencies]
cbindgen = "0.18.0"
那么lib.rs 只声明了一个非常简单的 extern hello world 函数:
#[no_mangle]
pub extern "C" fn test_fn() {
println!("Hello world from Rust!")
}
最后,我通过cdbindgen在build.rs中生成头文件:
extern crate cbindgen;
use std::env;
use std::path::Path;
use cbindgen::{Config, Builder};
fn main() {
let crate_env = env::var("CARGO_MANIFEST_DIR").unwrap();
let crate_path = Path::new(&crate_env);
let config = Config::from_root_or_default(crate_path);
Builder::new().with_crate(crate_path.to_str().unwrap())
.with_config(config)
.generate()
.expect("Cannot generate header file!")
.write_to_file("testprogram/headers/mycrate.h");
}
生成的header如下:
/* Generated with cbindgen:0.18.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
void test_fn(void);
我的 C 代码是以下简单程序:
#include <stdio.h>
#include "headers/mycrate.h"
int main() {
printf("Hello world from C!\n");
test_fn();
}
澄清一下,我的文件结构如下:
testprogram
|-- headers
| |-- mycrate.h
|
|-- main.c
|-- mycrate.dll
当我尝试编译和链接时,我得到一个链接器错误:
C:\Users\User\...\testprogram> gcc .\main.c -L.\mycrate.dll -o .\main
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Pau\AppData\Local\Temp\cccQGbDk.o:main.c:(.text+0x1b): undefined reference to `test_fn'
collect2.exe: error: ld returned 1 exit status
其他信息
奇怪的是,在 WSL (Linux) 中编译时,我得到了一个 .so Linux 库,它只是正确链接:
$ gcc main.c -L./mycrate.so -o main
$ ./main
Hello world from C!
Hello world from Rust!
我在这里缺少什么?我想这只是一个链接问题,但我找不到它的来源。任何帮助表示赞赏!
编辑
我也尝试过在链接时使用绝对路径。
我目前正在使用MinGW。
编辑 2
还尝试与 cargo 生成的包含库 mycrate.dll.lib 链接:
C:\Users\User\...\testprogram> gcc .\main.c -L.\mycrate.dll.lib -o .\main
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Pau\AppData\Local\Temp\ccL0sH7B.o:main.c:(.text+0x1b): undefined reference to `test_fn'
collect2.exe: error: ld returned 1 exit status
rustc --version --verbose 输出为:
C:\Users\User\...\testprogram> rustc --version --verbose
rustc 1.50.0 (cb75ad5db 2021-02-10)
binary: rustc
commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b
commit-date: 2021-02-10
host: x86_64-pc-windows-msvc
release: 1.50.0
【问题讨论】:
-
命令不应该是
gcc .\main.c -l.\mycrate.dll -o .\main吗?-Land-lare different -
用
-l试过,但我有同样的错误。如果我没记错的话-L是指定库的路径,而-l将在PATH中搜索库。还尝试使用绝对路径但没有运气。 -
你在 MinGW 或 MSVC 中使用 Rust 吗?
-
我正在使用
MinGW进行编译。 -
在 Linux 上,程序直接与库链接(
.so文件在构建时和运行时都使用)。在 Windows 上,.dll文件仅在运行时使用,您应该使用“导入库”(带有.lib扩展名)链接。