【发布时间】:2018-06-15 12:28:13
【问题描述】:
我想将一个 UTF8 编码字符串数组传递到本机代码中。我是为一个字符串做的(因为它只是一个字节数组),但现在我想传递一个字符串数组。
因为我不知道数组的大小,所以我应该传递对它的引用。所以我写了一个结构体,它应该包含数组指针和它的长度:
[StructLayout(LayoutKind.Sequential)]
struct StringRef
{
[MarshalAs(UnmanagedType.LPArray)]
public byte[] Bytes;
public uint Length;
}
但是当我运行它时它失败了:
无法封送“StringRef”类型的字段“Bytes”:托管/非托管类型组合无效(数组字段必须与 ByValArray 或 SafeArray 配对)。
这是完整的代码示例。
托管代码:
public class RustInterop
{
[StructLayout(LayoutKind.Sequential)]
struct StringRef
{
[MarshalAs(UnmanagedType.LPArray)]
public byte[] Bytes;
public uint Length;
}
[DllImport("rust.dll")]
private static extern int println(StringRef[] array, uint count);
public static int Println(params string[] strings)
{
var array = strings.Select(str => Encoding.UTF8.GetBytes(str)).Select(bytes => new StringRef
{
Bytes = bytes,
Length = (uint)bytes.Length
}).ToArray();
return println(array, (uint) array.Length);
}
}
非托管代码:
#[repr(C)]
pub struct StringRef {
bytes: *const u8,
length: usize
}
#[no_mangle]
pub extern fn println(array: *const StringRef, count: usize) -> i32 {
let array_slice = unsafe { std::slice::from_raw_parts(array, count) };
for str in array_slice {
let slice = unsafe { std::slice::from_raw_parts(str.bytes, str.length) };
let str = std::str::from_utf8(slice);
match str {
Ok(str) => {
println!("{}", str);
},
Err(_) => return -1
};
}
1
}
【问题讨论】:
-
您必须手动整理所有内容。
-
@xanatos 我希望它是一个答案,但我仍然希望它可以通过属性以某种方式完成。
标签: c# .net arrays pinvoke marshalling