Pergunta

I'm trying to compare two images using:

       [DllImport("msvcrt.dll")]
private static extern int memcmp(IntPtr b1, IntPtr b2, long count);

public static bool CompareMemCmp(Bitmap b1, Bitmap b2)
{
    if ((b1 == null) != (b2 == null)) return false;
    if (b1.Size != b2.Size) return false;

    var bd1 = b1.LockBits(new Rectangle(new Point(0, 0), b1.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    var bd2 = b2.LockBits(new Rectangle(new Point(0, 0), b2.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

    try
    {
        IntPtr bd1scan0 = bd1.Scan0;
        IntPtr bd2scan0 = bd2.Scan0;

        int stride = bd1.Stride;
        int len = stride * b1.Height;

        return memcmp(bd1scan0, bd2scan0, len) == 0;
    }
    finally
    {
        b1.UnlockBits(bd1);
        b2.UnlockBits(bd2);
    }
}

I'm using the CompareMemCmp() like this (on_click event):

        Bitmap img1 = new Bitmap(@"C:\1\1.png");
        Bitmap img2 = new Bitmap(@"C:\1\2.png");

        if (CompareMemCmp(img1, img2) == true)
        { textBox1.Text = "Same"; }
        else { textBox1.Text = "Different"; }

Unfortunately an exception is thrown:

return memcmp(bd1scan0, bd2scan0, len) == 0;

PinvokeStackimbalance "A call to PInvoke function 'TextRecognition!TextRecognition.Form1::memcmp' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."

what might be the problem? I've already tried different methods to solve this problem..

Foi útil?

Solução

pinvoke.net says the signature should be

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count);

Edit: pinvoke.net has labeled the original version of the declaration as x64 only, but it too seems to run fine on x32 with just an added CallingConvention=CallingConvention.Cdecl.

Outras dicas

The signature should be:

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int memcmp(IntPtr b1, IntPtr b2, UIntPtr count);

The problems with the code in the question are

  1. The mismatch between calling conventions: msvcrt.dll exports its functions as cdecl.
  2. The count parameter is size_t in the native code which equates to pointer sized unsigned integer in .net, i.e. UIntPtr.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top