12
我在學習Rust,試圖找到C/C++與C#互操作的替代方案。如何將Rust的數組返回到C#
如何編寫Rust代碼,如下面的C代碼?這是我的防鏽代碼到目前爲止,沒有選項馬歇爾它:
pub struct PackChar { id: u32, val_str: String, }
#[no_mangle]
pub extern fn get_packs_char(size: u32) -> Vec<PackChar> {
let mut out_vec = Vec::new();
for i in 0 .. size {
let int_0 = '0' as u32;
let last_char_val = int_0 + i % (126 - int_0);
let last_char = char::from_u32(last_char_val).unwrap();
let buffer = format!("abcdefgHi{}", last_char);
let pack_char = PackChar {
id: i,
val_str: buffer,
};
out_vec.push(pack_char);
}
out_vec
}
上面的代碼試圖複製下面的C代碼,我可以用爲的就是互操作。
void GetPacksChar(int size, PackChar** DpArrPnt)
{
int TmpStrSize = 10;
*DpArrPnt = (PackChar*)CoTaskMemAlloc(size * sizeof(PackChar));
PackChar* CurPackPnt = *DpArrPnt;
char dummyString[]= "abcdefgHij";
for (int i = 0; i < size; i++,CurPackPnt++)
{
dummyString[TmpStrSize-1] = '0' + i % (126 - '0');
CurPackPnt->IntVal = i;
CurPackPnt->buffer = strdup(dummyString);
}
}
這種C代碼可以通過DLL導入在C#中訪問這樣的:
[Dllimport("DllPath", CallingConvention = CallingConvention.Cdecl)]
public static extern void GetPacksChar(uint length, PackChar** ArrayStructs)
PackChar* MyPacksChar;
GetPacksChar(10, &MyPacksChar);
PackChar* CurrentPack = MyPacksChar;
var contLst = new List<PackChar>();
for (uint i = 0; i < ArrL; i++, CurrentPack++)
contlist.Add(new PackChar() {
IntVal = CurrentPack->IntVal, buffer = contLst->buffer
});
我對C#interop知之甚少,但有一點對於使用任何外部語言的FFI都是正確的:不應該在'extern'函數中使用特定於Rust的類型,如'Vec'。可以在這種函數中使用的唯一類型是基本類型,如整型,浮點型和指針,以及由這些類型組成的'#[repr(C)]'結構。 –