gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 16:38:44 25 4
gpt4 key购买 nike

我已将结构数组从 C#(托管代码)传递到 C(非托管代码)。 struct的内存是在C#端分配的。该数组是用 C 代码填充的。我的代码是多线程的。数组的填充由一个线程完成,另一个线程从结构数组中读取已经填充的项目。但是在第一个线程退出之前我无法从第二个线程读取数据,但是内存由两个线程共享。

示例代码

C# 结构

public struct Data
{
public IntPtr str;

[MarshalAs(UnmanagedType.I4)]
public int id;
}

在C#端分配struct数组的内存

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);

第二个线程开始读取填充的结构数据,但第一个线程仍在为 rest 索引填充数据。在这种情况下,数据可用于_data[0].str_data[0].id 显示 0 但在 C 端它显示正确的填充值,即 5。请帮助解释为什么 struct 成员 int id 的数据为 0。正确的值仅在第一个线程结束后出现。但由于内存是共享的,因此一旦被非托管代码填充,它就必须可用。

我们将不胜感激任何帮助。

我希望即使线程 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]);

关于c# - 从 C# 传递到 C 代码的结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54501432/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com