Search code examples
c#c++marshallingintptr

c# unmanaged PInvoke AccessViolation


I have C++ DLL. When call method from this DLL in C# AccessViolation was been throwing. What in my code is wrong? Can someone help me? C++ Header part:

typedef PVOID X_HANDLE;
XREADER_API BOOL ReaderOpen(X_HANDLE *pxHandle);
XREADER_API BOOL ReaderReceiveW26(X_HANDLE xHandle, LPVOID pBuffer, DWORD nBufferSize);

Working Example part C++:

X_HANDLE hReader;
unsigned char xKeyBuffer[3];
ReaderOpen(&hReader);
ReaderReceiveW26(hReader,xKeyBuffer,sizeof(xKeyBuffer));

My C# Code:

[DllImport("reader.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool ReaderOpen(IntPtr reference);
[DllImport("reader.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool ReaderReceiveW26(IntPtr hReader, IntPtr pBuffer, uint xKeyBuffer);
    static void Main(string[] args)
    {
        byte[] received = new byte[3];
        IntPtr unmanagedPointer = Marshal.AllocHGlobal(received.Length);
        Marshal.Copy(received, 0, unmanagedPointer, received.Length);
        IntPtr hReader = Marshal.AllocHGlobal(sizeof(uint));
        var qqq = uint.Parse((Marshal.SizeOf(typeof(byte)) * received.Length).ToString());
        ReaderOpen(hReader);
        while (true)
        {
            if (ReaderReceiveW26(hReader, unmanagedPointer, qqq))

            {
                Console.WriteLine("!");
            }
        }
    }

AccessViolation throwing at ReaderReceiveW26(hReader, unmanagedPointer, qqq)

Thanks for your patience!


Solution

  • Thanks to Hast Passant comment! If we want use IntPtr or smth which edited by unmanaged code we need use

    out paramName
    

    For PVOID we can pass real c# type.

    Working example:

    [DllImport("reader.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
    public static extern bool ReaderOpen(out IntPtr reference);
    [DllImport("reader.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
    public static extern bool ReaderReceiveW26(IntPtr hReader, byte[] pBuffer, uint xKeyBuffer);