我正在尝试使用C#中的System.Runtime.InteropServices.ComTypes.IStream,但我遇到了一些麻烦.根据MSDN,C#定义如下所示:
void Read(
byte[] pv,
int cb,
IntPtr pcbRead
)
Run Code Online (Sandbox Code Playgroud)
基本上,我可以从流中读取数据,但上面的"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;
}
Run Code Online (Sandbox Code Playgroud)
同样,问题是"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;
}
Run Code Online (Sandbox Code Playgroud)
不使用unsafe关键字也可以这样做:
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);
}
Run Code Online (Sandbox Code Playgroud)
如果您偶尔使用此方法,则应使用Marshal.CoTaskMemFree()来释放内存.