【问题标题】:c# create unmanaged object* arrayc# 创建非托管对象*数组
【发布时间】:2018-05-15 14:22:30
【问题描述】:

我需要创建一个非托管对象的可变长度数组,但我也需要该数组是非托管的,所以我不能使用 List 或其他类,但我必须以 c 方式对其进行 malloc/realloc。

这是我的代码:

unsafe class A{
    unsafe private int a1, a2;
    unsafe public byte* arr;
}

在不同的类方法上,我想做这样的事情:

private unsafe A* arr = Marshal.AllocHGlobal(array_size * Marshal.SizeOf<A>());

现在我有这些问题:

  1. 如何将 IntPtr 转换为 A*? OR 确实存在适当的 c# malloc/realloc 功能? 如果我 .dll 导入真正的 c/c++ realloc 函数会 使用起来安全吗?
  2. 如何获得指向 A 非托管对象的 A* 指针?如果我尝试使用 '&',它会说“无法获取 [...] 托管对象的地址”,但它不应该被管理。我在类声明中做错了吗?

可选:为什么 sizeof(A) 不起作用但 Marshal.SizeOf() 没问题?

【问题讨论】:

  • 各种性能原因但只是对一小段临界值的代码,大多是使用memcpy导入的.dll。我以 c# 开始我的项目,认为不安全的 c# 与纯 c 相同,现在我知道我错了,但我不想重写我的整个程序。
  • 你的 A 不是非托管的,它只是普通的 .NET 类(用“unsafe”关键字标记它不会改变任何东西,而且是多余的)。
  • @evk 那么我如何创建一个非托管的 A 对象?
  • @Slai 对于我发布的完全相同的代码,我在 VS 2017 中收到编译错误,你改变了什么吗?
  • @DamianoDiVincenzo 你不能。无非就是编写一些 c/c++ 代码,然后将其编组到 .net 世界。

标签: c# arrays object unmanaged


【解决方案1】:

你不能使用 C# 类来做这些事情,但你可以使用 struct:

[StructLayout(LayoutKind.Sequential)]
struct A
{
    public int A1;
    public int A2;
}

int array_size = 5;
// just cast IntPtr to A*
A* arr = (A*) Marshal.AllocHGlobal(array_size * Marshal.SizeOf<A>());
// set first element of unmanaged array
arr[0] = new A {A1 = 1, A2 = 2};
// set second
arr[1] = new A {A1 = 3, A2 = 4};

// alternative syntax:
// set first element
*arr = new A { A1 = 5, A2 = 6 };
// set second element
*(arr + 1) = new A { A1 = 5, A2 = 6 };
// get first element
var first = *arr;
var second = *(arr + 1);
Console.WriteLine(first.A1 + " " + first.A2);
Marshal.FreeHGlobal((IntPtr)arr);

【讨论】:

  • 这可行,但它在堆栈上,难道不能在堆上这样做吗?
  • @DamianoDiVincenzo 它不在堆栈上 - 它在您使用“AllocHGlobal”分配的非托管内存中。或者你的意思是不同的?
  • 我认为你是对的。抱歉,我对通常在堆栈上的“结构”感到困惑,但在这种情况下,我想它应该分配在指针区域内。
猜你喜欢
  • 2011-02-07
  • 2010-12-28
  • 2013-01-05
  • 2013-01-26
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 2017-08-16
相关资源
最近更新 更多