将 Mat 对象 C++ 传递给 Unity

pass Mat object C++ to Unity

我想从 C++ 代码 return 一个 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 Files\Unity\Editor\Unity.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 构造函数,which accepts external data pointer, to make the object not release/destruct the corresponding memory location data points to. You can read about this behaviour in Mat::release()

你的代码有问题

  1. Mat img(HEIGHT, WIDTH, CV_8UC3) 分配了一个 CV_8UC3 类型的内存块,大小为 HEIGHT*WIDTH,它没有被使用(因为你正在改变 data 成员变量指向一个无论如何,不​​同的内存位置),
  2. 在函数退出时,img 被析构,这会导致调用 release(),后者又会析构 frameData,即 而不是 预期的行为。

将前两行改为阅读

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

并且如果您将 resultArray 传递给 C#,您很可能 而不是 管理 pointed-to-memory 的生命周期,您很可能有内存泄漏。 @Programmer 在他对你之前问题的回答中已经建议你应该在 C# 中分配内存,将其传递给 C++,并在 C++ 端写入 in-place。

简而言之,你应该有这样的东西:

#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;
}