2015-04-01 137 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

您只需要为动态创建的对象释放内存,当变量超出范围时,静态对象将被析构函数销毁。

相关问题