键盘快捷键

在章节间导航

S/ 在书中搜索

? 显示此帮助

Esc 隐藏此帮助

在 Rust 中创建你的第一个 DLL

作为一种具有与 C 和 C++ 类似链接支持的系统编程语言,在 Rust 中构建 DLL 相当简单。然而,Rust 有其自己的库概念,这与 C 和 C++ 的库概念大相径庭,因此这只是找到正确配置以生成所需输出的问题。

与大多数 Rust 项目一样,你可以从 Cargo 开始并获得一个基本模板,但它非常简单,我们这里将手动构建它,以了解其中涉及的内容。让我们创建如下目录结构:

> hello_world
  Cargo.toml
  > src
    lib.rs

只有两个目录和两个文件。有一个 hello_world 目录,其中包含整个项目。在该目录中,我们有一个 Cargo.toml 文件,其中包含项目或包的元数据,以及编译包所需的信息。

[package]
name = "hello_world"
edition = "2021"

[lib]
crate-type = ["cdylib"]

至少,[package] 部分包含包的名称和编译所用的 Rust 版本。

纯 Rust 库通常不包含 [lib] 部分。当你需要专门控制项目如何使用和链接时,这是必需的。在这种情况下,我们使用“cdylib”,它表示一个动态系统库,在 Windows 上映射到 DLL。

src 子目录包含 lib.rs Rust 源文件,我们可以在其中添加希望从 DLL 导出的任何函数。这是一个简单的例子:

#[no_mangle]
extern "system" fn HelloWorld() -> i32 {
    123
}

[no_mangle] 属性只是告诉编译器禁用任何名称混淆,并使用函数名称作为导出的标识符。extern "system" 函数限定符表示函数所需的 ABI 或调用约定。“system”字符串表示系统特定的调用约定,在 Windows 上通常映射到“stdcall”。

就是这样!你现在可以构建包,它将生成一个 DLL。

> cargo build -p hello_world

Cargo 会将生成的二进制文件放到目标目录中,你可以在其中从任何其他编程语言中使用它们。

> dir /b target\debug\hello_world.*
hello_world.d
hello_world.dll
hello_world.dll.exp
hello_world.dll.lib
hello_world.pdb

这是一个简单的 C++ 示例:

#include <stdint.h>
#include <stdio.h>

extern "C" {
    int32_t __stdcall HelloWorld();
}

int main() {
    printf("%d\n", HelloWorld());
}

你可以使用 MSVC 如下构建:

cl hello_world.cpp hello_world.dll.lib

可以使用 dumpbin 工具进一步检查导入和导出。

> dumpbin /nologo /exports hello_world.dll

Dump of file hello_world.dll

File Type: DLL

  Section contains the following exports for hello_world.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001000 HelloWorld = HelloWorld
> dumpbin /nologo /imports hello_world.exe

Dump of file hello_world.exe

File Type: EXECUTABLE IMAGE

  Section contains the following imports:

    hello_world.dll
             140017258 Import Address Table
             140021200 Import Name Table
                     0 time date stamp
                     0 Index of first forwarder reference

                           0 HelloWorld