为了账号安全,请及时绑定邮箱和手机立即绑定

从 C# 代码传递到 C 代码的结构数组

从 C# 代码传递到 C 代码的结构数组

C#
慕村225694 2022-08-20 17:39:36
我已将一个结构数组从 C#(托管代码)传递到 C(非托管代码)。结构的内存在 C# 端分配。该数组以 C 代码填充。我的代码是多线程的。数组的填充由一个线程完成,另一个线程从结构数组中读取已填充的项。但是我无法从第二个线程读取数据,直到第一个线程退出,但是内存由两个线程共享。示例代码C# 结构public struct Data{    public IntPtr str;    [MarshalAs(UnmanagedType.I4)]    public int id;}在 C# 端分配结构数组的内存GCHandle[] handles = new GCHandle[10];for (int i = 0; i < 10; i++){     _data[i] = new Data();     byte[] bd = new byte[100];     handles[i] = GCHandle.Alloc(bd, GCHandleType.Pinned);     data[i].str = handles[i].AddrOfPinnedObject();}第一个线程将此结构数组_data传递给非托管代码(C 代码)以使用 func 进行填充void func([In,Out] Data[] _data);第二个线程开始读取填充的结构数据,但第一个线程仍在填充静态索引的数据。在这种情况下,数据可用于但显示0,但在C端它显示正确的填充值,即5。请帮助为什么结构成员int id的数据为0。正确的值仅在第一个线程结束后出现。但是,由于内存是共享的,因此,一旦被非托管代码填充,它必须立即可用。_data[0].str_data[0].id任何帮助将不胜感激。我希望即使线程 1 没有结束,线程 2 也必须能够获取已在非托管代码中填充的索引值。
查看完整描述

1 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

由于将托管数组传递给非托管代码,因此 clr 会先将该数组复制到另一个内存块中,然后将其传递给非托管函数。非托管函数完成后,clr 会将内存封送回托管数组,然后得到结果。


解决方案是将数组地址直接与不安全代码一起使用。


extern void func(Data* data);


fixed(Data* p = _data)

{

    func(p);

}

如果您不喜欢不安全的代码,由于结构数组的内存是顺序的,因此您可以传递第一个元素的引用。但我不确定这是否足够安全。


extern void func(ref Data data);


func(ref _data[0]);


查看完整回答
反对 回复 2022-08-20
  • 1 回答
  • 0 关注
  • 102 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信