2015-10-18 82 views
0

我想在C++中使用C++/CLI中的OpenCV 3編寫一個薄包裝(實際上我需要的功能非常少)。在不使用新的情況下將原生數據存儲在C++/cli中

但是我不是很清楚如何我可以將我的Mat變量存儲在託管類中,如果我嘗試這樣做,因爲我得到,如預期的那樣,錯誤指出我不能混合本機和非本地成員。

從我收集我應該新的我的本地成員和存儲一個指針,但我不能這樣做在所有情況下,因爲許多OpenCV方法返回一個墊,而不是一個指針墊。

經過一些測試,我看到: - 如果我存儲一個指向新的Mat();這工作得很好,它將在 後面仍然可用 - 如果我嘗試存儲指向Mat的指針(由imread返回),它將在方法結束後損壞。

什麼是正確的方式來存儲墊或指針?

示例代碼:

public ref class Matrix 
    { 
    private: 
     Mat* mat; 
     msclr::interop::marshal_context marshalcontext; 
    public: 
     static Matrix^ FromFile(System::String^ FileName) 
     { 
      Matrix^ ret = gcnew Matrix();    
      msclr::interop::marshal_context context; 
      std::string StdFileName = context.marshal_as<std::string>(FileName); 
      Mat tmpmat = imread(StdFileName); 
      Mat * tmpmatptr = new Mat(50, 50, 1); // Works in all cases 
          //Mat * tmpmatptr = &tmpmat; // will NOT work out of the scope of this method 
      Console::WriteLine(tmpmat.cols); // Always works 
      Console::WriteLine(tmpmat.rows); // Always works 
      Console::WriteLine(tmpmatptr->cols); // Always works 
      Console::WriteLine(tmpmatptr->rows); // Always works 
      ret->mat = tmpmatptr; 
      return ret; 
     } 

     void Save(System::String^ FileName) 
     { 
      std::string StdFileName = marshalcontext.marshal_as<std::string>(FileName); 
// Code bellow works if tmpmatptr in previous method was assigned a new Mat, doesn't work if it was assigned a pointer to imread result 
      Console::WriteLine(mat->rows); 
      Console::WriteLine(mat->cols); 
      imwrite(StdFileName, *mat); 
     } 
    }; 

注:我不是在尋找替代品寫我自己的包裝,沒有那些我已經試過的滿意。

+0

這是一個標準的[懸擺指針錯誤(https://en.wikipedia.org/維基/ Dangling_pointer)。使用ret-> mat = new Mat(tmpmat)創建存儲在堆上的副本。不要忘記Matrix中的析構函數和終結器,它需要再次摧毀它。 –

回答

1

您有一個範圍問題。一旦你的功能結束,你的墊被解構並且內存不再有效。它在你用新創建它時起作用,因爲內存在活着並且在堆上,直到你調用它的刪除。

特別這個呼叫:

Mat * tmpmatptr = &tmpmat; 

這設置tmpmatpr等於tmpmat的指針是在當前功能疊加。在函數結束時,堆棧中的所有變量都被銷燬。

我想你想改變這是什麼:

Mat tmpmat = imread(StdFileName); 
Mat * tmpmatptr = new Mat(50, 50, 1); 

Mat tmpmat = imread(StdFileName); 
Mat * tmpmatptr = new Mat(tmpmat); 
+0

這樣做,非常感謝你。我是否正確假設如果它是另一種類型,讓我們假設鍵入「testA」沒有構造函數,那麼如果僅通過在其上創建方法的方法可檢索,則無法在所有方法中存儲它疊加麼?還是有一種通用的C++方法來做類似PromoteFromStackToHeap(myobj)的事情? –

+0

隨時。許多建立良好的C++類確實擁有良好的拷貝構造函數,但很多都沒有。有一種方法,雖然它非常複雜。一般來說,你可以使用[std :: memcpy](http://www.cplusplus.com/reference/cstring/memcpy/)。這將原始內存數據從對象複製到另一個位置。但是我會認爲這很危險,除非你完全知道你在做什麼。 – GDub

相關問題