C# 调用 Rust 编写的 dll 之四:string
文中所有的程序运行环境为:windows 10 64bit,Net 5.0,Rust 1.51;乌龙哈里 2021-05-06
C# 调用 Rust 编写的 dll 系列:
Rust中的 str 是 utf8 编码的 u8 数组,我们按这个原则来传递字符串。
1、输入字符串:
接上面系列的程序,rust lib.rs 添加
#[no_mangle]//不写这个会把函数名编译成其他乱七八糟的 pub extern fn input_str(ptr:*const u8,len:usize){ let str=unsafe{ let slice=std::slice::from_raw_parts(ptr, len); std::str::from_utf8(slice) }; println!("Rust Dll get string: {}",str.unwrap()); }
c# 调用:
using System.Text;//Encoding 要引用这个
[DllImport("D:\\LabRust\\Learn\\ln_dll\\target\\release\\rustdll.dll", EntryPoint = "input_str", CallingConvention = CallingConvention.Cdecl)] public static extern void InputStr(byte[] arr, uint len); static void TestInputStr(string s) { var data = Encoding.UTF8.GetBytes(s + "\0"); //转成 \0 结尾的以utf编码的 u8 数组 InputStr(data, (uint)data.Length); } static void Main(string[] args) { string s = "abcde"; TestInputStr(s); Console.WriteLine($"C# string: {s}"); Console.Read(); } /*输出结果: Rust Dll get string: abcde C# string: abcde */
2、输出 string
由于 [u8] 不是 FFI 安全的,所以要在 c# 里先设定 byte[] 的大小,然后在 rust dll 里面往输入的 byte[] 中添加字符串的内容。具体如下代码。
#[no_mangle]//不写这个会把函数名编译成其他乱七八糟的 pub extern fn output_str(ptr:*const u8,len:usize){ let s="你好abcde"; println!("Rust Dll output string: {}",s); let data=s.as_bytes(); if data.len()<len{ unsafe{ let p=ptr as *mut u8;//裸指针,很危险! for (i,&v) in data.iter().enumerate(){ p.add(i).write(v); } // for i in 0..data.len(){ // p.add(i).write(data[i]); // } } } }
cargo build --release 后,用 c# 调用:
using System.Linq;//下面用到 lambda [DllImport("D:\\LabRust\\Learn\\ln_dll\\target\\release\\rustdll.dll", EntryPoint = "output_str", CallingConvention = CallingConvention.Cdecl)] public static extern void OutputStr(byte[] arr, uint len); static string TestOutputStr() { byte[] buff = new byte[1024];//预先指定字符串长度 OutputStr(buff, (uint)buff.Length); var data = buff.Where(x => x > 0).ToArray(); return Encoding.UTF8.GetString(data); } static void Main(string[] args) { Console.WriteLine($"C# string: {TestOutputStr()}"); Console.Read(); } /* 输出结果: Rust Dll output string: 你好abcde C# string: 你好abcde */