2017-08-08 19 views
2

我正在接受一個C DLL,它接受嵌套的尖端結構形式的參數。它簡化了C#的形式是這樣的:如何在C#中實例化堆中的結構

struct Point 
{ 
    public double X; 
    public double Y; 
} 

struct Rectangle 
{ 
    public unsafe Point* LowLeft; 
    public unsafe Point* TopRight; 
} 

的問題是,當我想要實例結構Rectangle。如何在堆上創建一個Point實例,然後將其地址分配給LowLeftTopRight字段?

一些錯誤的方法:

  • 直接使用C#new關鍵字是語法錯誤:

    r.LowLeft =新的點();

  • 使用虛擬變量似乎當我們離開的範圍是錯誤的,因爲它是在堆上分配的,因而被釋放:

    VAR啞=新的點(); r.LowLeft = @dummy;

+0

可能的重複https://stackoverflow.com/questions/4853213/are-structs-always-stack-allocated-or-sometimes-heap-allocated –

+0

@Sinatr這個問題與你提到的不一樣。 – melmi

+0

@丹瑞森這個問題是相關的,但不相同。我知道哪裏可以分配一個結構。但這不是重點。我真正想要的是一個指向該結構的指針。 – melmi

回答

2

說到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字段阻止您使用此聲明,但值得放在後面。

+0

請指出結構指針可以簡單地由'SuperStruct * ptr =(SuperStruct *)pointer.ToPointer();' – melmi

+0

@ M.Elmi構建。當我在某處添加'SuperStruct *'時,它給我一個編譯器錯誤'不能取得地址,獲取大小或者聲明一個指向託管類型的指針('Program.SuperStruct')'它甚至不會用不安全標誌進行編譯:( –

+1

恕我直言,這是因爲字符串字段在你的'struct'中。'string's是託管類,當進入'unsafe'字段時會導致問題。 – melmi

相關問題