Я пытаюсь использовать Систему. Время выполнения. 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" после чтения, хотя "буфер", кажется, содержит допустимые данные.
Предполагается, что вы передадите указатель на этот аргумент. Функция 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().
. У меня нет опыта работы с 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;
}
}