C#调用Rust dll测试
Posted henreash
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#调用Rust dll测试相关的知识,希望对你有一定的参考价值。
C#调用Rust dll,重点在于字符串传递,其他类型比较自然。可以给函数传递json字符串,在传出json字符串,两端通过json序列化、反序列化,可以方便处理参数数据。也可以传递不带字符串的结构体(结构体内含字符串的情况没有验证)。
小的结构体实例序列号反序列化速度很快,C#端序列号后,调用10000次Rust端函数,执行反序列化后修改对象成员,再次序列号,仅耗时36ms。开发中使用字符串传递参数和传出处理结果,完全可行。
没什么难点,直接上码:
Rust:
use std::thread;
use libc::c_char, uint32_t;
use std::ffi::CStr, CString;
use std::str;
extern crate serde;
extern crate serde_json;
#[macro_use] //引入serde_derive中的宏
extern crate serde_derive;
#[derive(Debug, Serialize, Deserialize)]
struct Address
street: String,
city: String,
#[derive(Debug, Serialize, Deserialize)]
struct Person
name: String,
age: u8,
address: Address,
phones: Vec<String>,
impl Person
fn default() -> Self
Person
name: "zhangsan".to_string(),
age: 18u8,
address: Address
street: "East nanjing road".to_string(),
city: "shanghai".to_string(),
,
phones: vec!["12345678".to_string(), "23456789".to_string()],
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Kind
Ok,
Done,
BufferTooSmall,
ArgumentNull,
InternalError,
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DbResult
kind: Kind,
id: u32,
#[no_mangle]
pub extern fn GetDbResult() -> DbResult
DbResult
kind: Kind::Done,
id: 100u32,
#[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!");
fn mkstr(s: *const c_char) -> String
let c_str = unsafe
assert!(!s.is_null());
CStr::from_ptr(s)
;
let r_str = c_str.to_str().expect("Could not successfully convert string form foreign code!");
String::from(r_str)
#[no_mangle]
pub extern fn free_string(s: *mut c_char)
unsafe
if s.is_null()return
CString::from_raw(s)
;
#[no_mangle]
pub extern fn result(istr: *const c_char) -> *mut c_char
let s = mkstr(istr);
let values: Person = serde_json::from_str(&s).unwrap();
println!("Hello,,welcome to rust world,you name change to -rust!",values.name,values.name);
let values2 = Personname:values.name + "-rust", ..values;
let json = serde_json::to_string_pretty(&values2).unwrap();
let cex = CString::new(json).expect("Failed to create CString!");
cex.into_raw()
Cargo.toxml
[package]
name = "rust_code"
version = "0.1.0"
authors = ["henreash <nmhys@126.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2.48"
serde = "*"
serde_derive = "*"
serde_json = "*"
[lib]
name="rust_code"
crate-type=["dylib"]
C#代码:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SharpProcessor
public partial class Form1 : Form
[DllImport("rust_code.dll")]
internal static extern void process();
[DllImport("rust_code.dll")]
internal static extern void free_string(IntPtr str);
[DllImport("rust_code.dll")]
internal static extern StringHandle result(string inputs);
[DllImport("rust_code.dll")]
internal static extern DbResult GetDbResult();
public Form1()
InitializeComponent();
private Person GetTestData()
return new Person
Name = "zhangsan",
Age = 18,
Addresss = new Address
Street = "East nanjing road",
City = "Shanghai",
,
Phones = new List<string>
"12345678",
"23456789",
;
private void button1_Click(object sender, EventArgs e)
//process();
//var str = "hello world, i come form c sharp";
var str = JsonConvert.SerializeObject(GetTestData());
using (var str2 = result(str))
MessageBox.Show(str2.AsString());
var dbResult = GetDbResult();
MessageBox.Show($"dbResult._result dbResult._id");
internal class StringHandle : SafeHandle
public StringHandle() : base(IntPtr.Zero, true)
public override bool IsInvalid
get return false;
public string AsString()
int len = 0;
while (Marshal.ReadByte(handle, len) != 0) ++len;
byte[] buffer = new byte[len];
Marshal.Copy(handle, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
protected override bool ReleaseHandle()
Form1.free_string(handle);
return true;
public class Person
[JsonProperty("name")]
public string Name get; set;
[JsonProperty("age")]
public byte Age get; set;
[JsonProperty("address")]
public Address Addresss get; set; = new Address();
[JsonProperty("phones")]
public List<string> Phones get; set; = new List<string>();
public class Address
[JsonProperty("street")]
public string Street get; set;
[JsonProperty("city")]
public string City get; set;
[StructLayout(LayoutKind.Sequential)]
public struct DbResult
public enum Kind : uint
Ok,
Done,
BufferTooSmall,
ArgumentNull,
InternalError
public readonly Kind _result;
public readonly uint _id;
public bool IsSuccess()
return _result == Kind.Ok || _result == Kind.Done;
public bool IsDone()
return _result == Kind.Done;
public bool IsBufferTooSmall()
return _result == Kind.BufferTooSmall;
运行结果:
耗时测试(首次执行耗时稍长,后面在执行,稳定在36ms左右):
private void button1_Click(object sender, EventArgs e)
var stop = new Stopwatch();
stop.Start();
var str = JsonConvert.SerializeObject(GetTestData());
for (var i = 0; i < 10000; i++)
using (var str2 = result(str))
stop.Stop();
MessageBox.Show(stop.ElapsedMilliseconds.ToString());
以上是关于C#调用Rust dll测试的主要内容,如果未能解决你的问题,请参考以下文章
VS2017下创建C++动态库导出符合并完成调用测试(DLL可供C#调用)
VS2017下创建C++动态库导出符合并完成调用测试(DLL可供C#调用)