tags:

views:

253

answers:

7

The problem below is ralated to my previous question

http://stackoverflow.com/questions/2384932/converting-static-link-library-to-dynamic-dll

My first step was to develop a dll, that was done. (Thanks John Knoeller prakash. Your input was very helpful)

Now when i call the function in the dll from my c# application i get the error

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

Here is the C++ definition

 extern "C" DEMO2_API void Decompress(char* inp_buff, unsigned short* 
 inp_len, char* buffer_decomp,unsigned *output_len,unsigned short* errorCode);

My C# Converstion p/Involke

   private static extern void Decompress(
        byte[] inp_buff,
        ref ushort inp_len,
        byte[] buffer_decomp,
        ref int output_len,
        ref ushort errorCode
        );        

And I am calling it as below

    byte[] dst = new byte[2048];
    int outlen = 2048;
    ushort errorCode = 0;
    Decompress(src, (ushort )src.Length, dst, ref outlen,ref errorCode);
    return dst;

What is wrong?

A: 

I see a signature mismatch on the inp_len parameter. In the C++ definition you use a pointer to a short unsigned int, while in the C# method you use a ushort.

Maurits Rijk
I have edited it.
Manjoor
A: 

for pointers you must use IntPtr .net type

necrostaz
A: 

@necrostaz

It is not necessary that we use IntPtr for pointers.

Look below all of these four declarations are valid and currently i am using it.

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, String lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, StringBuilder lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, String lParam);

question is still open

Manjoor
A: 

In addition to the missing "ref" on the inp_len declaration that Maurits pointed out, you need to make sure that your pointer sizes match.

If you're running on a 32-bit operating system you should be OK, but if your code runs on 64-bit too, then you need to ensure that either:

  • You mark your .net entry assembly as x86 (not Any CPU)
  • or
  • You supply a 32-bit and 64-bit build of the C++ dll and install the correct one for the interop to call.
marklam
I understand. But i am running Win Xp Professional 32 bit and i have tried with IntPtr. Still getting same error..
Manjoor
Just to be sure, have you changed the signature to read "ref ushort inp_len"?
marklam
A: 

I have had the same problem two years ago. In my case the reason for the access violation was that the memory was allocated outside the DLL. As a solution I added two functions for memory allocation and deallocation to the DLL.

Another solution could be a change of the .net security settings. Some keywords are "Code Access Security Police Tool" (caspol.exe) and ".NET Framework Configuration Tool" (mscorcfg.msc). In VS there is also a security tab in the project property dialog. I'm not an expert in .net security so someone else should know more details.

Interesting.. I don't want to deal with .Net security.Can you please provide your solution for tha same.
Manjoor
Here are two links that may help you: http://ask.metafilter.com/79680/Calling-unmanaged-DLL-functions-from-C and http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/6e843243-baf4-4eb1-8a20-c691ad47762c
@alexj, it seems to be the reason behind this. But unfortunatlly, i could not understant what are they doing and how can i implement it in my own function. I appreaciate if you please describe a bit. Thanks..
Manjoor
A: 

The following code runs without any problems. It's very similar to yours:

C++:

extern "C" __declspec(dllexport) void TestFunction(char* inp_buff,
               unsigned short* inp_len,
               char* buffer_decomp,
               unsigned *output_len,
               unsigned short* errorCode)
{
    //copy input buffer to output buffer
    int size = min(*inp_len,*output_len);
    for(int i=0; i<size; i++)
        buffer_decomp[i] = inp_buff[i];

    errorCode = 0;
}

C#:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("TEST.DLL")]
    public static extern void TestFunction(byte[] inp_buff,
                                           ref ushort inp_len,
                                           byte[] out_buff,
                                           ref int out_len,
                                           ref ushort errorCode);

    static void Main(string[] args)
    {
        //prepare input buffer
        byte[] inp_buff = new byte[20];
        inp_buff[0] = (byte)'T';
        inp_buff[1] = (byte)'E';
        inp_buff[2] = (byte)'S';
        inp_buff[3] = (byte)'T';
        ushort inp_len = (ushort)inp_buff.Length;

        //prepare output buffer
        byte[] out_buff = new byte[20];
        int out_len = out_buff.Length;

        ushort errorCode = 0;
        TestFunction(inp_buff, ref inp_len, out_buff, ref out_len, ref errorCode);

        //see if copying was successful
        for(int i=0; i<out_len; i++)
            Console.Out.Write(out_buff[i]);
    }
}

Try it out. I have taken a look at the open parts of the library you are using. Here is a direct excerpt of the function lzo_decomp:

   in = lzo_malloc(IN_LEN);
      out = lzo_malloc(OUT_LEN);
   wrkmem = lzo_malloc(LZO1Z_999_MEM_COMPRESS);
   if (in == NULL || out == NULL || wrkmem == NULL)    
    {

     printf("out of memory\n");

    }


   in_len = IN_LEN;
   lzo_memset(in,0,in_len );
   lzo_memset ( out, 0, OUT_LEN );  


   memcpy ( out, &input_buffer, inp_buff_len);

lzo_free(wrkmem);
lzo_free(out);
lzo_free(in);  


r = lzo1z_decompress(out,*inp_len,in,&out_len,NULL );

For serenity: "in" and "out" are not the function arguments for the input and output buffers but temporary pointers. What can you see (beside from bad formatted code)? The only two buffers lzo1z_decompress is called with are "in" and "out". And these two buffers are freed before the call. I'm not surprised that there is an access violation. I only can underline nobugz's advice: Contact the author.

A: 

The 4th parameter need to be passed using out mode instead of ref. That solved the problem.

Manjoor