Вызов функции C ++ из приложения C #. Попытка чтения или записи в защищенную память - PullRequest
4 голосов
/ 05 марта 2010

Проблема ниже относится к моему предыдущему вопросу

Преобразование статической библиотеки ссылок в динамическую dll

Мой первый шаг заключался в разработке dll, что было сделано.(Спасибо John Knoeller prakash. Ваш вклад был очень полезен)

Теперь, когда я вызываю функцию в dll из моего приложения на c #, я получаю ошибку

"Попытка чтения или записизащищенная память. Это часто указывает на то, что другая память повреждена. "

Вот определение C ++

 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
        );        

И я называю это как показано ниже

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

Что не так?

Ответы [ 7 ]

0 голосов
/ 09 марта 2010

Следующий код работает без проблем. Это очень похоже на ваше:

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]);
    }
}

Попробуйте. Я взглянул на открытые части используемой вами библиотеки. Вот прямая выдержка из функции 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 );

Для безмятежности: «in» и «out» - это не аргументы функции для входных и выходных буферов, а временные указатели. Что вы можете увидеть (кроме плохо отформатированного кода)? Единственные два буфера, с которыми вызывается lzo1z_decompress, это "in" и "out". И эти два буфера освобождаются перед вызовом. Я не удивлен, что есть нарушение прав доступа. Я только могу подчеркнуть совет Нобугза: свяжитесь с автором.

0 голосов
/ 12 марта 2010

4-й параметр необходимо передать, используя режим out вместо ref.Это решило проблему.

0 голосов
/ 07 марта 2010

У меня была такая же проблема два года назад. В моем случае причиной нарушения доступа было то, что память была выделена за пределами DLL. В качестве решения я добавил две функции для выделения и освобождения памяти в DLL.

Другим решением может быть изменение настроек безопасности .net. Некоторые ключевые слова: «Инструмент безопасности кода доступа» (caspol.exe) и «Инструмент настройки .NET Framework» (mscorcfg.msc). В VS также есть вкладка безопасности в диалоге свойств проекта. Я не эксперт по безопасности .net, поэтому кто-то другой должен знать больше деталей.

0 голосов
/ 05 марта 2010

В дополнение к отсутствующему значению ref в объявлении inp_len, на которое указал Мориц, необходимо убедиться, что размеры указателей совпадают.

Если вы работаете в 32-битной операционной системе, у вас должно быть все в порядке, но если ваш код работает и в 64-битной среде, вам необходимо убедиться, что:

  • Вы пометили свою сборку .net как x86 (не любой процессор)
  • или
  • Вы предоставляете 32-битную и 64-битную сборку DLL C ++ и устанавливаете правильную для вызова взаимодействия.
0 голосов
/ 05 марта 2010

@ necrostaz

Нет необходимости использовать IntPtr для указателей.

Смотрите ниже, все эти четыре объявления действительны, и в настоящее время я использую их.

[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);

вопрос еще открыт

0 голосов
/ 05 марта 2010

для указателей вы должны использовать IntPtr .net type

0 голосов
/ 05 марта 2010

Я вижу несоответствие сигнатуры по параметру inp_len. В определении C ++ вы используете указатель на короткое целое без знака, а в методе C # вы используете ushort.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...