在不使用 new 的情况下在 C++/cli 中存储本机数据
Storing native data in C++/cli without using new
我正在尝试在 C++/CLI 中围绕 OpenCV 3 编写一个薄包装器(我实际需要的功能很少),以便从 C# 中使用。
但是我不太清楚如何将我的 Mat 变量存储在托管 class 中,如果我尝试按原样进行操作,我会如预期的那样收到一个错误,说明我可以'不要混合本地和非本地成员。
据我所知,我应该更新我的本地成员并存储指向它们的指针,但是我不能在所有情况下都这样做,因为很多 OpenCV 方法 return a Mat 和不是指向 Mat 的指针。
经过一些测试,我看到:
- 如果我存储一个指向新 Mat() 的指针;这很好用,以后仍然可用
- 如果我尝试存储指向 Mat 的指针(如 return 由 imread 编辑),它将在方法结束后损坏。
存储 Mat 或指向它的指针的正确方法是什么?
示例代码:
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);
}
};
注意:我不是在寻找替代方法来编写自己的包装器,none 我试过的包装器令人满意。
你的范围有问题。一旦您的功能结束,您的垫子就会被解构并且该内存不再有效。当您使用 new 创建它时它会起作用,因为内存然后处于活动状态并在堆上,直到您对其调用 delete。
特别是这个电话:
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);
我正在尝试在 C++/CLI 中围绕 OpenCV 3 编写一个薄包装器(我实际需要的功能很少),以便从 C# 中使用。
但是我不太清楚如何将我的 Mat 变量存储在托管 class 中,如果我尝试按原样进行操作,我会如预期的那样收到一个错误,说明我可以'不要混合本地和非本地成员。
据我所知,我应该更新我的本地成员并存储指向它们的指针,但是我不能在所有情况下都这样做,因为很多 OpenCV 方法 return a Mat 和不是指向 Mat 的指针。
经过一些测试,我看到: - 如果我存储一个指向新 Mat() 的指针;这很好用,以后仍然可用 - 如果我尝试存储指向 Mat 的指针(如 return 由 imread 编辑),它将在方法结束后损坏。
存储 Mat 或指向它的指针的正确方法是什么?
示例代码:
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);
}
};
注意:我不是在寻找替代方法来编写自己的包装器,none 我试过的包装器令人满意。
你的范围有问题。一旦您的功能结束,您的垫子就会被解构并且该内存不再有效。当您使用 new 创建它时它会起作用,因为内存然后处于活动状态并在堆上,直到您对其调用 delete。
特别是这个电话:
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);