0

I have a project with 3 parts:

  1. Managed C# project with a callback which gives me a Bitmap (it should have PixelFormat = Format24bppRgb). I've tried several ways to convert the Bitmap into something I could pass to part 2, that's the last thing I've tried:

    public int BufferCB(IntPtr pBuffer, int BufferLen)
    {
        byte[] aux = new byte[BufferLen];
        Marshal.Copy(pBuffer, aux, 0, BufferLen);
        String s_aux = System.Text.Encoding.Default.GetString(aux);
        wrappedClassInstance.GetBitmap(s_aux);
    }
    
  2. Managed C++/CLI to wrap item 3:

    int WrappedClass::GetBitmap(array<System::Byte>^ s_in) {
        pin_ptr<unsigned char> pin = &s_in[0];
        unsigned char* p = pin;
        return privateImplementation->GetBitmap(p);
    }
    
  3. Unmanaged C++ application that uses OpenCV. I want to load this data into a Mat with:

    Mat myMat;
    int NativeClass::GetBitmap(unsigned char *s_in) {
    
        // If there's no input:
        if (!s_in) {
            return -1;
        }
        /* h and w are defined elsewhere */
        myMat = Mat(h, w, CV_8UC3, (void *)s_in, Mat::AUTO_STEP));
        imwrite("test.bmp", myMat);
        return 0;
    }
    

When the the imwrite function is reached an exception is thrown: "System.Runtime.InteropServices.SEHException (0x80004005)". It doesn't say much, but I'm guessing the data I passed into the Mat got corrupted when I've marshalled it.

Before, I was trying to pass the data without a wrapper:

[DllImport("mydll.dll", ...)]
static extern void GetBitmap(IntPtr pBuffer, int h, int w);

void TestMethod(IntPtr pBuffer, int BufferLen)
{
    // h and w defined elsewhere
    // GetBitmap is essentially the same as in item 3.
    GetBitmap(pBuffer, BufferLen, h, w);
}

and that worked (it saved the Bitmap into the file), but because the DLL stays attached until I kill the process that solution is not good enough for me. I also don't want to "mirror" the Mat class into my project, as I know Mat should accept data from some char*.

Please help, how can I do this? Am I doing wrong type conversions?

Thank you.

Eric Omine
  • 489
  • 4
  • 15
  • I've changed part 2 a little, it's edited now. – Eric Omine Mar 27 '15 at 12:43
  • Found [this](http://stackoverflow.com/questions/13990264/access-violation-when-using-pin-ptr), I think I'll have to copy the array into unmanaged heap before passing the pointer to my private implementation, or figure out how to pin the IntPtr in C#. – Eric Omine Mar 27 '15 at 13:18

1 Answers1

0

I've changed part 2 to memcpy unmanaged memory into native memory, just to be sure. But the real problem with my code was that everytime I wanted to get a new Mat, I'd call Mat constructor:

Mat myMat;
int MyClass::GetBitmap(unsigned char* s_in) {
    myMat = Mat(...)
}

Instead, I did:

Mat myMat;
int MyClass::GetBitmap(unsigned char* s_in) {
    Mat aux;
    aux = Mat(...)
    aux.copyTo(myMat);
    aux.release();
}

... and now my code is working perfectly.

EDIT: Removed some parts which used new Mat(...), it was a typo and it wouldn't compile because I'm using Mat, not Mat*.

Eric Omine
  • 489
  • 4
  • 15