Jus*_*tin 6 linker compiler-errors ffi visual-studio rust
我一直在尝试让 Rust 与 Windows 上的 C 库链接,但 Rust 无法找到我需要的函数。看来我的函数签名是错误的,但 Rust 可以找到该.lib文件。
我将其范围缩小到非常简单的 C 和 Rust 代码,但仍然不知道如何让它工作:
test.c——使用 Visual Studio 2015 编译
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
typedef struct MyStruct {
int32_t i;
} MyStruct;
MyStruct my_func(const MyStruct *s) {
MyStruct result;
result.i = s->i + 1;
return result;
}
int32_t my_func2() {
return 42;
}
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
库文件
extern crate libc;
use libc::int32_t;
#[link(name = "MyLib")]
extern {
pub fn my_func2() -> int32_t;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
unsafe {
assert_eq!(42, my_func2());
}
}
}
Run Code Online (Sandbox Code Playgroud)
或者lib.rs:
extern crate libc;
use libc::int32_t;
#[repr(C)]
pub struct MyStruct {
i: int32_t
}
#[link(name = "MyLib")]
extern {
pub fn my_func(s: *mut MyStruct) -> MyStruct;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
unsafe {
let mut s = MyStruct{ i: 10 };
let s = my_func(&mut s as *mut MyStruct);
assert_eq!(11, s.i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我收到的错误消息:
extern crate libc;
use libc::int32_t;
#[link(name = "MyLib")]
extern {
pub fn my_func2() -> int32_t;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
unsafe {
assert_eq!(42, my_func2());
}
}
}
Run Code Online (Sandbox Code Playgroud)
Cargo.toml
extern crate libc;
use libc::int32_t;
#[repr(C)]
pub struct MyStruct {
i: int32_t
}
#[link(name = "MyLib")]
extern {
pub fn my_func(s: *mut MyStruct) -> MyStruct;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
unsafe {
let mut s = MyStruct{ i: 10 };
let s = my_func(&mut s as *mut MyStruct);
assert_eq!(11, s.i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您是否检查过您的.lib文件是否有任何符号/导出的函数?:
> dumpbin /exports /symbols MyLib.lib
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file MyLib.lib
File Type: LIBRARY
Run Code Online (Sandbox Code Playgroud)
这意味着您的.lib文件没有任何导出的符号。您可能想过使用__declspec(dllexport),但这似乎不适用于静态.lib文件。
使用 Visual Studio 有点麻烦,但在 VS 2015 中使用它的方法如下:
填写详细信息:
LIBRARY MyLib
EXPORTS
my_func @1
my_func2 @2
Run Code Online (Sandbox Code Playgroud)右键单击您的项目,单击属性,并确保您的项目配置正确:
在 Librarian 下,确保设置文件.def:
构建.lib文件。如果您执行正确,dumpbin再次运行应该如下所示:
> dumpbin /exports /symbols MyLib.lib
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file MyLib.lib
File Type: LIBRARY
COFF SYMBOL TABLE
000 01015E97 ABS notype Static | @comp.id
001 00000000 SECT2 notype External | __IMPORT_DESCRIPTOR_MyLib
002 C0000040 SECT2 notype Section | .idata$2
003 00000000 SECT3 notype Static | .idata$6
004 C0000040 UNDEF notype Section | .idata$4
005 C0000040 UNDEF notype Section | .idata$5
006 00000000 UNDEF notype External | __NULL_IMPORT_DESCRIPTOR
007 00000000 UNDEF notype External | MyLib_NULL_THUNK_DATA
String Table Size = 0x5C bytes
COFF SYMBOL TABLE
000 01015E97 ABS notype Static | @comp.id
001 00000000 SECT2 notype External | __NULL_IMPORT_DESCRIPTOR
String Table Size = 0x1D bytes
COFF SYMBOL TABLE
000 01015E97 ABS notype Static | @comp.id
001 00000000 SECT2 notype External | MyLib_NULL_THUNK_DATA
String Table Size = 0x22 bytes
Exports
ordinal name
1 my_func
2 my_func2
Summary
D2 .debug$S
14 .idata$2
14 .idata$3
8 .idata$4
8 .idata$5
12 .idata$6
Run Code Online (Sandbox Code Playgroud)将生成的.lib文件(确保从正确的目录执行此操作;请注意,64 位和 32 位编译到不同的文件夹)复制到 Rust 项目的根目录:
+ MyRustProject/
\
+ src/
+ Cargo.toml
+ MyLib.lib
Run Code Online (Sandbox Code Playgroud)返回构建配置并构建.dll:
将其复制.dll到与.lib
现在,当您构建 Rust 项目时,它应该可以工作。请注意,您必须为与 Rust 相同的平台构建 VS 项目,因此,就我而言,这意味着 x64,而不是 x86。
有关.def文件的更多信息,请参阅微软的官方文档。