C# 调用 Rust 编写的 dll 之四:string

C# 调用 Rust 编写的 dll 之四:string

文中所有的程序运行环境为:windows 10 64bit,Net 5.0,Rust 1.51;乌龙哈里 2021-05-06

C# 调用 Rust 编写的 dll 系列:

  1. 《C# 调用 Rust 编写的 dll 之一:创建 dll》
  2. 《C# 调用 Rust 编写的 dll 之二:输入输出简单数值》
  3. 《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 + ""; //转成 结尾的以utf编码的 u8 数组 var data = Encoding.UTF8.GetBytes(s); //已经指定大小了,没必要再以结尾 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
*/

  

原文地址:https://www.cnblogs.com/leemano/p/14733475.html