如何在 C# 中实例化堆中的结构
How to instantiate an structure in heap in C#
我正在使用 C DLL,它接受嵌套指向结构形式的参数。它的简化 C# 形式是这样的:
struct Point
{
public double X;
public double Y;
}
struct Rectangle
{
public unsafe Point* LowLeft;
public unsafe Point* TopRight;
}
当我想实例化结构Rectangle
时出现了问题。如何在堆上创建 Point 实例,然后将其地址分配给 LowLeft
和 TopRight
字段?
一些错误的方法:
直接使用 C# new 关键字在语法上是错误的:
r.LowLeft = 新点();
使用虚拟变量似乎是错误的,因为它是在堆上分配的,因此在我们离开作用域时会被释放:
var dummy = new Point();
r.LowLeft = @dummy;
根据 M.Elmi 在评论中所说的内容,我开始尝试将结构放入非托管内存中。不幸的是,我不知道如何检查它是否在堆或堆栈或诸如此类的东西上,但它现在肯定位于非托管内存中......
static void Main(string[] args)
{
SuperStruct myStruct = new SuperStruct() { MyName = "Dan", MyNumber = 1 };
SuperStruct myOtherStruct;
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf<SuperStruct>());
Marshal.StructureToPtr(myStruct, pointer, false);
myOtherStruct = Marshal.PtrToStructure<SuperStruct>(pointer);
Console.WriteLine($"Name: {myOtherStruct.MyName}, Number: {myOtherStruct.MyNumber}.");
Console.ReadLine();
}
struct SuperStruct
{
public int MyNumber;
public string MyName;
}
总的来说,这个过程是:1) 使用 Marshal.AllocHGlobal
设置一些准备好包含数据的非托管内存。 2) 使用 Marshal.StructureToPtr
方法设置内存。 3) 使用 Marshal.PtrToStructure<T>
方法从非托管内存中检索该结构。
也有人指出(M.Elmi 在评论中)我们可以声明类型化指针,只要结构定义中不包含托管类型,如下所示:
unsafe
{
SuperStruct* ptr = (SuperStruct*)pointer.ToPointer();
}
在我的具体示例中,string
字段阻止您使用此声明,但值得将其放在此处作为后验。
我正在使用 C DLL,它接受嵌套指向结构形式的参数。它的简化 C# 形式是这样的:
struct Point
{
public double X;
public double Y;
}
struct Rectangle
{
public unsafe Point* LowLeft;
public unsafe Point* TopRight;
}
当我想实例化结构Rectangle
时出现了问题。如何在堆上创建 Point 实例,然后将其地址分配给 LowLeft
和 TopRight
字段?
一些错误的方法:
直接使用 C# new 关键字在语法上是错误的:
r.LowLeft = 新点();
使用虚拟变量似乎是错误的,因为它是在堆上分配的,因此在我们离开作用域时会被释放:
var dummy = new Point(); r.LowLeft = @dummy;
根据 M.Elmi 在评论中所说的内容,我开始尝试将结构放入非托管内存中。不幸的是,我不知道如何检查它是否在堆或堆栈或诸如此类的东西上,但它现在肯定位于非托管内存中......
static void Main(string[] args)
{
SuperStruct myStruct = new SuperStruct() { MyName = "Dan", MyNumber = 1 };
SuperStruct myOtherStruct;
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf<SuperStruct>());
Marshal.StructureToPtr(myStruct, pointer, false);
myOtherStruct = Marshal.PtrToStructure<SuperStruct>(pointer);
Console.WriteLine($"Name: {myOtherStruct.MyName}, Number: {myOtherStruct.MyNumber}.");
Console.ReadLine();
}
struct SuperStruct
{
public int MyNumber;
public string MyName;
}
总的来说,这个过程是:1) 使用 Marshal.AllocHGlobal
设置一些准备好包含数据的非托管内存。 2) 使用 Marshal.StructureToPtr
方法设置内存。 3) 使用 Marshal.PtrToStructure<T>
方法从非托管内存中检索该结构。
也有人指出(M.Elmi 在评论中)我们可以声明类型化指针,只要结构定义中不包含托管类型,如下所示:
unsafe
{
SuperStruct* ptr = (SuperStruct*)pointer.ToPointer();
}
在我的具体示例中,string
字段阻止您使用此声明,但值得将其放在此处作为后验。