2015-04-01 57 views
0

我有一個C++/CLI方法調用C的結構和方法:我需要在C中刪除非託管對象++/CLI

在C頭:

typedef struct { 
    int left; 
    int top; 
    int right; 
    int bottom; 
} frame_t; 

typedef struct { 
    int  width; 
    int  height; 
    int  group; 
    int  nb_hints; 
    frame_t *hints; 

    frame_t view; 
    frame_t dest; 
    int  page; 
} image_t; 

int resize_to_fill(image_t *image, int width, int height); 

的C++/CLI包裝:

public ref class Frame { 
public: 
    int Left; 
    int Top; 
    int Right; 
    int Bottom; 

    property int Width { 
     int get() { 
      return (Right - Left); 
     } 
    } 
    property int Height { 
     int get() { 
      return (Bottom - Top); 
     } 
    } 

    Frame() { 
     Top = 0; 
     Left = 0; 
     Bottom = 0; 
     Right = 0; 
    } 

internal: 
    frame_t ToNative() { 
     frame_t f; 
     f.left = Left; 
     f.top = Top; 
     f.right = Right; 
     f.bottom = Bottom; 
     return f; 
    } 

    Frame(const frame_t &f) { 
     Left = f.left; 
     Top = f.top; 
     Right = f.right; 
     Bottom = f.bottom; 
    } 
}; 

public ref class Image { 
private: 
    void init(int nb_hints) { 
     this->view = gcnew Frame(); 
     this->dest = gcnew Frame(); 
     this->page = 0; 
     this->Hints = gcnew array<Frame^>(nb_hints); 
    } 

public: 
    int Width; 
    int Height; 
    array<Frame^>^ Hints; 

    property int Group { 
     int get() { 
      return group; 
     } 
    } 
    property int Page { 
     int get() { 
      return this->page; 
     } 
    } 
    property Frame^ View { 
     Frame^ get() { 
      return this->view; 
     } 
    } 
    property Frame^ Dest { 
     Frame^ get() { 
      return this->dest; 
     } 
    } 

    Image(int nb_hints) { 
     this->init(nb_hints); 
    } 

    Image() { 
     this->init(0); 
    } 

internal: 
    Frame^ view; 
    Frame^ dest; 
    int page; 
    int group; 

    Image(image_t native) { 
     this->Width = native.width; 
     this->Height = native.height; 

     this->Hints = gcnew array<Frame^>(native.nb_hints); 
     for (int i = 0; i < native.nb_hints; i++) 
     { 
      this->Hints[i] = gcnew Frame(native.hints[i]); 
     } 

     this->group = native.group; 
     this->page = native.page; 
     this->dest = gcnew Frame(native.dest); 
     this->view = gcnew Frame(native.view); 
    } 

    image_t ToNative() { 
     image_t i; 
     i.width = this->Width; 
     i.height = this->Height; 
     i.group = this->Group; 

     // hints 
     i.nb_hints = this->Hints->Length; 
     i.hints = new frame_t[this->Hints->Length]; 
     for (int nb = 0; nb < this->Hints->Length; nb++) 
     { 
      i.hints[nb] = this->Hints[nb]->ToNative(); 
     } 

     // output values 
     i.page = this->Page; 
     i.view = this->View->ToNative(); 
     i.dest = this->Dest->ToNative(); 

     return i; 
    } 
}; 

// later, in another class 
static int ResizeToFill(Image^ %image, int width, int height) { 
    image_t native = image->ToNative(); 

    int result = resize_to_fill(&native, width, height); 

    image = gcnew Image(native); 

    // do I need to do this ? 
    delete *native; 

    return result; 
} 

我是否需要刪除本地結構實例?

我已經搜索了這個答案,但是關於處理託管資源的情況要多於非託管資源,這對大多數人來說似乎是很明顯的。我是C/C++的新手,所以我沒有全部的內存管理反應。

+0

如果這是C/C++,並且native是一個'image_t'類型的對象,並且它不是一個指針,那麼不需要刪除它,它將在您退出該函數時被刪除。如果它是一個指針並且內存是動態分配的,那麼你需要釋放它。同樣,你不刪除對象,它是指針指向的內存 – Gopi 2015-04-01 10:01:41

+0

如果從[你的上一個問題]的類型定義(https://stackoverflow.com/questions/24548468/passing-managed-c-arrays-to - 從非託管c)在這個問題上沒有改變:不,清理是沒有必要的。然而,'delete * native;'應該不會被編譯,因爲'* native'不是一個有效的表達式。 (也不應該'刪除本地;'因爲'native'不是一個指針。)它們是否改變了? – Wintermute 2015-04-01 10:30:53

+0

我已經更新了問題以包含完整的代碼(我認爲?)。在我寫這個問題之前,我寫了一個'native'實際上是一個指針,但是我注意到我不需要它,所以我只是在寫問題的時候切換(並且沒有檢查它會工作:()。 – thomasb 2015-04-01 13:31:03

回答

1
image = gcnew Image(native); 

它完全取決於此聲明的作用。您正在使用的庫不是一個常見的圖像封裝類不是System :: Drawing :: Image,因此無法從您的代碼段中分辨出來。

這個庫的程序員有兩種方法可以實現它。如果他做得很聰明,那麼他就會成爲你的問題,並創建一個淺拷貝。換句話說,Image的一個新實例與原生共享相同的基礎像素緩衝區。或者他可以創建一個深拷貝併爲Image對象創建一個新的像素緩衝區。在這種情況下,您可以安全地銷燬image_t對象。

.NET中也存在這樣的差異,Bitmap :: Clone()使淺拷貝,Bitmap(Image ^)構造函數進行深度複製。兩者之間存在巨大差異,淺拷貝最多需要幾個納秒。如果圖像很大,深度複製需要很長時間,可能是毫秒

如果處理相當痛苦的淺拷貝,您可能無法更改Image類的終結器。你必須保留image_t *並獲得一個很好的信號,表明Image對象不再被使用,所以你可以安全地刪除它。你將不得不重構你的代碼。如果你猜錯了,那麼你有一個非常討厭的問題,它不能保證你的代碼崩潰。你有一個不太可能導致訪問衝突的懸掛指針。當你測試時似乎工作得很好,當你沒有看時,會破壞顯示的圖像或無法識別地崩潰你的程序。

查看圖書館的源代碼或文檔以瞭解其功能非常重要。

+0

對不起,我忘了:我有添加了完整的封裝代碼(我認爲?)。Image對象實際上不是像素緩衝區,只是它的位置結構。無論如何非常有趣:) – thomasb 2015-04-01 13:33:09

+0

我認爲'image_t'是通過值傳遞給重載的構造函數,那麼它的副本呢?我錯了嗎 ? 「ResizeToFill」方法中使用的'image_t'是否仍然「綁定」到「Image」實例? – thomasb 2015-04-01 14:39:51

+0

嗯,似乎是這樣。我完全根據image_t實際上存儲圖像的假設來回答我的答案。我不想重寫它,它的大圖並沒有錯。當你複製一個沒有任何指針成員的簡單結構時,你正在做一個深層複製。 – 2015-04-01 15:08:59

1

您只需要爲動態創建的對象釋放內存,當變量超出範圍時,靜態對象將被析構函數銷燬。

相關問題