C# и IStream. Читать

Я пытаюсь использовать Систему. Время выполнения. InteropServices. ComTypes. IStream от C#, но я испытываю некоторые затруднения. Согласно MSDN, определение C# похоже на это:

void Read(
    byte[] pv,
    int cb,
    IntPtr pcbRead
)

В основном я могу считать данные с потока, но вышеупомянутое "pcbRead" значение всегда "0" (даже при том, что массив байтов содержит мои данные). Делая некоторое чтение, кажется, как будто pcbRead аргумент несколько хитер для установки правильно (хотя я довольно плохо знаком с C#).

Так или иначе мой код в основном похож на это:

myPtr = (IntPtr)0;
int buffSize = 8192;
byte[] buffer = new byte[buffSize];
while (true)
{
  strm.Read(buffer, buffSize, myPtr);
  fs.Write(buffer, 0, myPtr.ToInt32());
  if (myPtr.ToInt32() < buffSize) break;
}

Снова, проблема состоит в том, что "myPtr" все еще содержит "0" после чтения, хотя "буфер", кажется, содержит допустимые данные.

5
задан Jeff Godfrey 24 December 2009 в 16:37
поделиться

2 ответа

Предполагается, что вы передадите указатель на этот аргумент. Функция IStream::Read() запишет в указатель количество байт, которые на самом деле были прочитаны. Для этого необходим небезопасный код на C#, например:

unsafe static int Read(System.Runtime.InteropServices.ComTypes.IStream strm,
  byte[] buffer) {
  int bytesRead = 0;
  int* ptr = &bytesRead;
  strm.Read(buffer, buffer.Length, (IntPtr)ptr);
  return bytesRead;
}

Также возможно сделать это без опасного ключевого слова:

private static IntPtr ReadBuffer;

static int Read(System.Runtime.InteropServices.ComTypes.IStream strm,
  byte[] buffer) {
  if (ReadBuffer == IntPtr.Zero) ReadBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)));
  strm.Read(buffer, buffer.Length, ReadBuffer);
  return Marshal.ReadInt32(ReadBuffer);
}

Если вы используете этот метод только изредка, то для освобождения памяти следует использовать функцию Marshal.CoTaskMemFree().

.
7
ответ дан 14 December 2019 в 04:39
поделиться

У меня нет опыта работы с IStream, но, глядя на ваш код, я вижу некоторую потенциальную ошибку.
. В начале переменная myPtr установлена на ноль. IntPtr работает как указатели на Си++, поэтому я думаю, что этот метод ожидает, что он запишет значение в то место, куда ссылается myPtr.

Можете попробовать?

unsafe 
{
    int pcbRead = 0;
    int buffSize = 8192;
    byte[] buffer = new byte[buffSize];
    while (true)
    {
        // taking address of pcbRead
        strm.Read(buffer, buffSize, new IntPtr(&pcbRead)); 
        fs.Write(buffer, 0, pcbRead);
        if (pcbRead < buffSize) break;
    }
}
0
ответ дан 14 December 2019 в 04:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: