首页 文章

将大量数据从Rust FFI库返回给C#调用者的最快方法是什么? [关闭]

提问于
浏览
3

我正在开发一个.NET C#程序,它通过Rust FFI调用我自己的Rust库,使用extern C关键字并由DllImport加载 .

我这样做是因为我想将复杂的计算委托给Rust . 在从Rust库处理之后,预计会将大量数据返回给C# . 当它在C#中使用时,这些数据应该是 List<MyDataRecord> .

然后我的问题是:

  • 来自Rust,传回这些数据的最佳方法是什么?通过一个指向一个内存块的指针,像一个结构阵列一样排列?

  • C#如何找回这样的内存块指针?这里有线程安全问题吗?

  • 如何在C#中快速将这样的内存数据块转换为 List<MyDataRecord>

1 回答

  • 1

    我们需要回答的第一个问题是:谁将负责分配和释放内存?如果您事先知道将返回多少元素,那么您可以使用C#代码或Rust代码分配内存 . 如果你没有't know in advance how many elements will be returned, then you have 2 options: 1) have the C# code ask the Rust code how many elements will be returned (if that'可能),那么从C#分配内存; 2)让Rust代码分配内存 . 如果从C#(例如托管阵列)分配托管内存,则可以让垃圾收集器释放内存 . 如果从C#或Rust中分配非托管内存,那么你需要提供一个释放内存的函数 . 请记住,生成结果的Rust代码需要显式"leak"数组/ Vec ,否则你的函数会在返回之前释放内存!

    你'll find it difficult to use .NET' s List<T> 类型与非托管代码 . 您应该使用数组 .

    另一个需要考虑的重要方面是struct 's layout. You' ll必须将 #[repr(C)] 添加到Rust结构中,并将 [StructLayout(LayoutKind.Sequential)][StructLayout(LayoutKind.Explicit)] (取决于结构中的类型)添加到C#结构中,以确保双方以相同的方式布局结构的字段在记忆中 .

    在C#代码中为Rust函数定义 DllImport 时,可以使用MarshalAs attribute注释参数和返回值,以告诉.NET运行时如何对参数和返回值进行编组或解组 . 特别是,UnmanagedType enumerationLPArray 成员可能对您的情况有所帮助,但请注意it uses CoTaskMemAlloc and CoTaskMemFree to manage memory . 如果Rust代码负责分配内存,您还可以通过将指针定义为 IntPtr 并使用Marshal.PtrToStructure来解组结构并使用Marshal.SizeOf来将指针偏移到下一个元素来手动执行解组 .

相关问题