1.认识Cargo
Cargo 是 Rust 的构建系统和包管理器。可以构建代码、编译下载依赖库
在存放项目目录路径 打开Powershell
查看Cargo版本
cargo --version
2.创建库项目
输入命令:
cargo new rust_dll --lib
2.1 项目结构
3.编写库逻辑代码
3.1 编辑 src/lib.rs 文件
#[no_mangle] // 表明 编译时函数方法名不会被混淆
pub extern fn hello_rust(){
println!("hello world!");
}
#[no_mangle]
pub extern fn return_value() -> i32 { // extern 表示函数是一个外部函数接口
123
}
其中,#[no_mangle]为了编译时函数方法名不会被混淆。extern表示该函数是一个外部函数接口。
3.2 编辑Cargo.toml 文件
新增lib 节点
[package]
name = "rust_dll"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[lib]
name = "RustDll" # 生成的dll 名称,可以随便取
crate-type = ["cdylib"] # 表明是 C规范动态库
关于 crate-type 有很多种,这里只对比下 dylib 和 cdylib
dylib(动态库)
会在编译的时候,生成动态库(Linux 上为 .so, MacOS 上为 .dylib, Windows 上为 .dll)。
动态库是平台相关的库。动态库在被依赖并链接时,不会被链接到目标文件中。这种动态库只能被 Rust 写的程序(或遵循 Rust 内部不稳定的规范的程序)调用。这个动态库可能依赖于其它动态库(比如,Linux 下用 C 语言写的 PostgreSQL 的 libpq.so,或者另一个编译成 "dylib" 的 Rust 动态库)。
cdylib(C规范动态库)
与 dylib 类似,也会生成 .so, .dylib 或 .dll 文件。但是这种动态库可以被其它语言调用(因为几乎所有语言都有遵循 C 规范的 FFI 实现),也就是跨语言 FFI 使用。这个动态库可能依赖于其它动态库(比如,Linux 下用 C 语言写的 PostgreSQL 的 libpq.so)。
4.编译
进入到项目根目录,执行编译命令
cargo build --release
这里有个警告:说明生成的dll 命名不规范,我是以C# 规范命名,与Rust 的规范冲突
最终生成 target/release/RustDll.dll
5.C# 代码调用 RustDll.dll
5.1 创建测试控制台程序
[DllImport("RustDll.dll", EntryPoint = "hello_rust", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloRust();
[DllImport("RustDll.dll", EntryPoint = "return_value", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReturnValue();
static void Main(string[] args)
{
Console.WriteLine("Rust Hello world");
HelloRust();
var r = ReturnValue();
Console.WriteLine("Rust Return Value " + r);
Console.ReadKey();
}
5.2 把生成的RustDll.dll 复制到Debug目录,并启动控制台程序
5.3 报错
由于我的电脑是 64位 ,Rust默认生成与电脑架构相同的类库
并且项目属性->生成
平台目标是 Any CPU,并且首选32位
解决报错
1. 去掉勾选 这个 首选32位 的选项
2.平台目标 选择 x64
5.4 运行结果