Rust初步(六):在C#中使用Rust组件
上一篇文章,我们通过实例比较了一下C#和Rust的性能表现,应该说在Release模式下面,Rust进行计算密集型的运算还是有些比较明显的优势的。那么,我们有没有可能,在C#中做一些快速应用开发,而一些核心的算法用Rust来实现呢?答案是可以的。
编写Rust代码
下面这段代码,保存在lib.rs文件中
use std::thread; #[no_mangle] pub extern fn process(){ let handles :Vec<_> =(0..10).map(|_|{ thread::spawn(||{ let mut x= 0; for _ in (0..5_000_000){ x+=1 } x }) }).collect(); for h in handles{ println!("Thread finished with count={}",h.join().map_err(|_| "Could not join a thread!").unwrap()); } println!("done!"); }
这段代码的几个关键点在于
1.声明为pub,也就是说要让外部可以访问到
2.声明为extern,意思应该也是说希望外部可以访问
3.添加一个标记 #[no_mangle],这个开关据说是阻止编译器在编译的时候,重命名函数。我也还不是很理解,先照这么做吧
其他部分就是标准的Rust代码了
生成Rust的动态链接库
默认情况下,Rust编译的库叫做静态链接库,如果我们需要编译动态链接库的话,需要在Cargo.toml文件中定义
然后,运行cargo build -- release命令生成动态链接库(dll)
我们在输出目录中,可以看到一个countlib.dll 的动态链接库文件
在C#中使用这个动态链接库
你可以将countlib.dll放在C#编译输出目录的根目录下面
using System; using System.Threading.Tasks; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { [DllImport("countlib.dll",CallingConvention= CallingConvention.Cdecl)] public static extern void process(); static void Main(string[] args) { Stopwatch watch = new Stopwatch(); watch.Start(); //Parallel.For(0, 10, i => //{ // var x = 0; // for (int j = 0; j< 5000000; j++) // { // x += 1; // } // Console.WriteLine("线程:{0} 完成计数",Thread.CurrentThread.ManagedThreadId); //}); process();//调用Rust里面的程序process进行计算 watch.Stop(); Console.WriteLine("耗时:{0}秒", watch.Elapsed.TotalSeconds); Console.Read(); } } }
在Debug模式下面的耗时为 0.002秒(提升太明显了吧)
在Release模式下面的耗时为0.002秒(基本上跟Debug模式不相上下,很神奇吗)
那么,这个性能表现,几乎接近了直接使用Rust的性能,比原先用C#的方式提高了5倍。
如此说来,计算密集型(尤其是需要用到多线程,多核)的任务,可以用Rust来编写,然后在C#中调用。
【特别注意】
cargo build默认情况下会根据当前计算机的配置进行编译,例如我是64位的计算机,那么编译出来的dll也是64位的,在C#中用的时候,就需要同样设置为64位,否则就会出现错误
那么,cargo build是否可以指定对应的平台进行编译呢?可以通过指定 --target参数来实现,可用的值主要有
x86_64-pc-windows-gnu
i686-unknown-linux-gnu
x86_64-unknown-linux-gnu
详细可以参考 http://doc.crates.io/manifest.html
我用下面这样用就可以编译一个通用的dll(既能用于32位,也能用于64位——采用WOW模式)
其实这个编译选项,类似于我们在Visual Studio中使用Any CPU进行编译
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
2013-08-26 在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
2013-08-26 一个在ASP.NET中利用服务器控件GridView实现数据增删改查的例子