Search code examples
c#c++dllexport

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt


I am trying to pass a byte array to a c++ dll:

c++:

extern "C" __declspec(dllexport) char* myfunction(byte bytes[])
{
    char *byteschar = (char*)bytes;
    //do somethings with it
    return byteschar;
}

c#:

[DllImport("mydll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
        ,CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string myfunction(byte[] bytes);

but I get a System.AccessViolationException when I call myfunction.

When I run the executable without the debugger it seems to be working fine


Solution

  • If you want a buffer be allocated in C# and filled in C++, the approach is a little bit different.

    You should allocate a kind of "unmanaged" buffer, pass to the DLL and then convert the result and free the buffer. It's exactly the same way in C, but calling from a managed environment.

    Your C++ code should be something like:

    extern "C" __declspec(dllexport) void myfunction(char* buffer, int length)
    {
        //Fill buffer with something observing the maximum length of the buffer.
    }
    

    The signature of your DLL in C# should be:

    [DllImport("mydll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
            ,CharSet = CharSet.Ansi)]
    public static extern string myfunction(IntPtr buffer, Int32 length);
    

    To call it from C#, you should do:

        IntPtr unmanagedBuffer = Marshal.AllocHGlobal(100);
        // Your Unmanaged Call
        myfunction(unmanagedBbuffer, 100);
        string yourString = Marshal.PtrToStringUni(unmanagedBuffer);
        Marshal.FreeHGlobal(unmanagedBuffer);
    

    Don't forget to call FreeHGlobal if you don't want a memory leak in your app. It's interesting to protect this in "try/finally" clauses.

    Other observation is the encoding of the string. Uni, means Unicode. If you use another string representation, check for an equivalent PtrToStringXXX function.