结构的阵列从C#传递给C代码

问题描述 投票:3回答:1

我已经通过从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);

第二个线程开始读取填充结构数据,但仍然第一个线程用于填充其他指标数据。在这种情况下,数据可用于_data[0].str_data[0].id正显示出0,但位于C端它显示了正确的填充值即5,请帮忙为什么结构成员INT ID数据即将0的正确值只来自第一线后结束。但是由于存储器是共享的,必须因为它是由非托管代码填写尽快上市。

任何帮助将得到高度赞赏。

我想了即使线程1不结束线程2必须能够获取其已填补在非托管代码率的值。

c# marshalling unmanaged
1个回答
2
投票

因为传递一个管理的阵列到非托管代码,CLR将复制阵列到另一个存储器块,然后再传递到非托管函数。非托管函数完成后,CLR将元帅内存放回管理的阵列,那么你得到的结果。

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

extern void func(Data* data);

fixed(Data* p = _data)
{
    func(p);
}

如果你不喜欢不安全代码,由于结构阵列的存储器是连续的,则可以通过第一元件的参考。但我不知道是否足够安全。

extern void func(ref Data data);

func(ref _data[0]);
© www.soinside.com 2019 - 2024. All rights reserved.