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文件中定義

image

然后,運行cargo build -- release命令生成動態鏈接庫(dll)

image

我們在輸出目錄中,可以看到一個countlib.dll 的動態鏈接庫文件

image

 

在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秒(提升太明顯了吧)
image
 
在Release模式下面的耗時為0.002秒(基本上跟Debug模式不相上下,很神奇嗎)
image
 
那么,這個性能表現,幾乎接近了直接使用Rust的性能,比原先用C#的方式提高了5倍。
 
如此說來,計算密集型(尤其是需要用到多線程,多核)的任務,可以用Rust來編寫,然后在C#中調用。
 
【特別注意】
cargo build默認情況下會根據當前計算機的配置進行編譯,例如我是64位的計算機,那么編譯出來的dll也是64位的,在C#中用的時候,就需要同樣設置為64位,否則就會出現錯誤
image
 

那么,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模式)
image
 
其實這個編譯選項,類似於我們在Visual Studio中使用Any CPU進行編譯
image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM