将 Mat 对象C++传递给 Unity

pass Mat object C++ to Unity

本文关键字:Unity C++ Mat 对象      更新时间:2023-10-16

我想从 c++ 代码将一个 Mat 对象返回给 Unity。但是我在这样的 c++ 部分收到访问冲突错误

Unity Editor [version: Unity 2017.3.0f3_a9f86dcd79df]
SaliencyCV.dll caused an Access Violation (0xc0000005)
in module SaliencyCV.dll at 0033:270027f0.
Error occurred at 2018-03-06_235212.
C:Program FilesUnityEditorUnity.exe, run by Dilara.
43% memory in use.
16266 MB physical memory [9199 MB free].
18698 MB paging file [9861 MB free].
134217728 MB user address space [134185466 MB free].
Read from location 990d0000 caused an access violation.

下面是 c++ 代码:

uchar* cppMethod(uchar* frameData, int WIDTH, int HEIGHT, int* rows, int* cols)
{
Mat img(HEIGHT, WIDTH, CV_8UC3);
img.data = frameData;
flip(img, img, 0);
Mat result = calculateSaliency(img);
*rows = result.rows;
*cols = result.cols;
int length = result.rows * result.cols * 3;
uchar* tmpArr = result.data;
uchar* resultArray = new uchar[length];
for (int i = 0; i < length; i++)
{
resultArray[i] = tmpArr[i]; 
}
return resultArray;
}

有人可以帮助我吗?

您应该调用正确的Mat构造函数,该构造函数接受外部数据指针,以使对象不释放/破坏data指向的相应内存位置。您可以在Mat::release()中阅读有关此行为的信息。

代码的问题在于

  1. Mat img(HEIGHT, WIDTH, CV_8UC3)分配大小为HEIGHT*WIDTHCV_8UC3类型的内存块,该内存块未使用(因为无论如何,您正在更改data成员变量以指向不同的内存位置),
  2. 在函数退出时,img被破坏,这导致对release()的调用,这反过来又破坏了frameData,这不是预期的行为。

将前两行更改为阅读

Mat img(HEIGHT, WIDTH, CV_8UC3, frameData);

如果要将resultArray传递给 C#,则很可能没有管理指向内存的生存期,则很可能会发生内存泄漏。 @Programmer在回答您之前的问题时已经建议,您应该在 C# 中分配内存,将其传递给 C++,并在C++端就地写入。

简而言之,您应该具有以下内容:

#include <algorithm>
void cppMethod(uchar *frameData, uchar *out, const int WIDTH, const int HEIGHT,
int *rows, int *cols) {
/* this constructor will not manage frameData's lifetime */
Mat img(HEIGHT, WIDTH, CV_8UC3, frameData);
/* in-place operation */
flip(img, img, 0);
/* local variable --- it will be destructed properly */
Mat result = calculateSaliency(img);
/* well-defined if rows and cols are scalars passed by reference */
*rows = result.rows;
*cols = result.cols;
/* make sure length will not overflow */
int length = result.rows * result.cols * 3;
/* you don't need this */
// uchar *tmpArr = result.data;
/* you sholuld NOT do this */
// uchar *resultArray = new uchar[length];
// use std::copy from <algorithm>
// for (int i = 0; i < length; i++) {
//   resultArray[i] = tmpArr[i];
// }
std::copy(result.data, result.data + length, out);
// return resultArray;
}