2015-10-18 81 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

相关问题