将Mat对象C ++传递给Unity

时间:2018-03-06 21:36:40

标签: c++ opencv access-violation

我想从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 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;
}

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:2)

您应该调用正确的Mat构造函数which accepts external data pointer,以使对象不释放/破坏相应的内存位置data指向。您可以在Mat::release()中了解此行为。

您的代码存在的问题是

  1. Mat img(HEIGHT, WIDTH, CV_8UC3)分配一个大小为CV_8UC3的{​​{1}}内存块,但未使用(因为您要将HEIGHT*WIDTH成员变量更改为指向不同的内存位置,反正),
  2. 在功能退出时,data被销毁,从而导致对img的调用,而release()则会导致frameData 预期的行为
  3. 将前两行更改为

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