C ++ нарушение прав доступа при вызове функции dll - PullRequest
1 голос
/ 08 марта 2010

У меня есть определение функции в моей VC ++ Win32 DLL

DEMO2_API void ProcessData(char* i_buff, unsigned short i_len, char* o_buf,
unsigned *o_len, unsigned short *errorCode)
{
    __describe (i_buff,&i_len,o_buf,o_len,errorCode);
}

Эта dll-функция вызывается приложением c #. При вызове генерируется исключение нарушения прав доступа.

После повторного изучения я нашел причину моей проблемы.

http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/6e843243-baf4-4eb1-8a20-c691ad47762c

Но не мог понять, что именно они делают в примере кода. Может кто-нибудь объяснить это мне так?

А какой будет подпись P / Invoke в c # после внешнего выделения памяти?

Ответы [ 2 ]

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

Я изменил режим передачи O_len на out вместо ref , и он работает.

Спасибо всем за хорошие ответы и комментарии. Я надеюсь, что это было бы полезно для других участников сообщества (плюс те, кто гуглил ...)

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

C # использует IntPtr для представления внешней памяти. Указатели и ссылки C # могут использоваться только с памятью, предоставленной сборщиком мусора.

Класс System.InteropServices.Marshal предоставляет несколько методов для взаимодействия с собственными областями памяти, представленными IntPtr, конечно, они не безопасны для типов.

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

РЕДАКТИРОВАТЬ, чтобы добавить пример по запросу:

// this doesn't work right
void external_alloc_and_fill(int n, int* result)
{
  result = new int[n];
  while (n-- > 0) { result[n] = n; }
}

extern external_alloc_and_fill(int n, int* result)
int a = 5;
fixed (int* p = &a) {
  external_alloc_and_fill(17, p);
  // p still points to a, a is still 5
}

лучше

// works fine
void external_alloc_and_fill2(int n, int** presult)
{
  int* result = *presult = new int[n];
  while (n-- > 0) { result[n] = n; }
}

extern external_alloc_and_fill2(int n, ref IntPtr result)
int a 5;
IntPtr p = &a;
external_alloc_and_fill2(17, ref p);
// a is still 5 but p is now pointing to the memory created by 'new'
// you'll have to use Marshal.Copy to read it though
...