method
method

Reputation: 1389

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

Upvotes: 0

Views: 1568

Answers (2)

maszynaz
maszynaz

Reputation: 309

It suppose to be:

extern "C" __declspec(dllexport) char* myfunction(unsigned char * bytes)
{
    //do somethings with it
    return bytes;
}

Upvotes: 0

Eric Lemes
Eric Lemes

Reputation: 581

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.

Upvotes: 1

Related Questions