IntPtr в байтовый массив и обратно - PullRequest
6 голосов
/ 08 декабря 2010

Ссылка Как получить IntPtr из байта [] в C #

Я пытаюсь прочитать данные, на которые ссылается IntPtr, в байт [], а затем обратно в другой IntPtr. Указатель ссылается на изображение, снятое с устройства сканера, поэтому я также предположил, что для получения этой информации необходимо поместить ее в байтовый массив.

Я также не уверен, что метод Marshal.SizeOf () вернет размер данных, на которые ссылается IntPtr, или размер самого указателя.

Моя проблема в том, что я получаю сообщение об ошибке "Тип 'System.Byte []' не может быть маршалирован как неуправляемая структура; невозможно вычислить значимый размер или смещение"

IntPtr bmpptr = Twain.GlobalLock (hImage);

try
{
     byte[] _imageTemp = new byte[Marshal.SizeOf(bmpptr)];
     Marshal.Copy(bmpptr, _imageTemp, 0, Marshal.SizeOf(bmpptr));

     IntPtr unmanagedPointer = Marshal.AllocHGlobal(
         Marshal.SizeOf(_imageTemp));

     try
     {
           Marshal.Copy(_imageTemp, 0, unmanagedPointer, 
               Marshal.SizeOf(_imageTemp));

           Gdip.SaveDIBAs(
               string.Format("{0}\\{1}.{2}", CaptureFolder, "Test", "jpg"), 
               unmanagedPointer, false);
     }
     finally
     {
           Marshal.FreeHGlobal(unmanagedPointer);
     }
}
catch (Exception e)
{
      Scanner.control.Test = e.Message;
}

Ответы [ 2 ]

6 голосов
/ 08 декабря 2010

Исключение, сгенерированное вызовом SizeOf, является правильным; у метода нет возможности узнать, какова длина массива, который вы ему передаете, он просто имеет указатель.

Для этого самый простой способ получить данные - вызвать статический метод Copy для класса Маршала , передав указатель на неуправляемые данные, индекс и количество байтов для чтения. , а также предварительно выделенный буфер байтов для маршалинга данных в.

Что касается получения размера массива, то, как Антон Тихий указал в комментариях , выглядит (будьте очень осторожны здесь), который использует вызов Twain.GlobalLock(hImage) память, выделенная на GlobalAlloc, что означает, что вы можете сделать вызов функции GlobalSize API через слой P / Invoke, чтобы получить размер.

Если это , а не дескриптор чего-то, выделенного вызовом GlobalAlloc, тогда вам нужно выяснить, как модуль Twain выделяет память, и использовать соответствующий механизм для определения длины. памяти, на которую указывает IntPtr.

2 голосов
/ 08 декабря 2010

1 - я предполагаю, что bmpptr уже является неуправляемым указателем, если так, то зачем вам нужно «возвращаться туда и обратно» к неуправляемому указателю?не дает вам размер неуправляемого выделения памяти.

Используя Marshal.Copy, вы можете скопировать содержимое неуправляемой памяти в массив управляемых байтов, но вам нужно будет знать, сколько байтов нужно переместитьнеуправляемый буфер в управляемый буфер.В идеале API должен предоставлять эту информацию.

...