我想直接写入/读取多字节数组到/从文件,并建议使用PInvoke WriteFile/ReadFile。C#得到正确的IntPtr指向已经声明的变量
基本上我阅读的代码看起来像现在这样:
[DllImport("kernel32.dll", SetLastError = true)]
static extern unsafe int ReadFile(IntPtr handle, IntPtr bytes, uint numBytesToRead,
IntPtr numBytesRead, System.Threading.NativeOverlapped* overlapped);
..<cut>..
byte[,,] mb = new byte[1024,1024,1024];
fixed(byte * fb = mb)
{
FileStream fs = new FileStream(@"E:\SHARED\TEMP", FileMode.Open);
int bytesread = 0;
ReadFile(fs.SafeFileHandle.DangerousGetHandle(), (IntPtr)fb, Convert.ToUInt32(mb.Length), new IntPtr(bytesread), null);
fs.Close();
}
此代码引发AccessViolationException。 然而,下面的代码不会:
[DllImport("kernel32.dll", SetLastError = true)]
static extern unsafe int ReadFile(IntPtr handle, IntPtr bytes, uint numBytesToRead,
ref int numBytesRead, System.Threading.NativeOverlapped* overlapped);
..<cut>..
byte[,,] mb = new byte[1024,1024,1024];
fixed(byte * fb = mb)
{
FileStream fs = new FileStream(@"E:\SHARED\TEMP", FileMode.Open);
int bytesread = 0;
ReadFile(fs.SafeFileHandle.DangerousGetHandle(), (IntPtr)fb, Convert.ToUInt32(mb.Length), ref bytesread, null);
fs.Close();
}
不同的是,我宣布numBytesRead是裁判INT而不是IntPtr的。
然而,无处不在那里我找到了问题的答案“如何获得的IntPtr为int”,它是这样:
int x = 0;
IntPtr ptrtox = new IntPtr(x)
那么,我究竟做错了什么?为什么访问违规?
我正在使用IntPtr读取字节,因为我想读入多维数组。任何多维数组。这样,我可以为所有情况制作一个简单的虚拟包装器,并且将byte [,]或byte [,,]或其他任何内容传递给相同的函数,并且它将工作,因为“fixed(byte * fixedByteArray = buffer)”不关心缓冲区有多少维度。但是,如果我宣布参考字节[,]我不能通过字节[,,]例如 – Istrebitel
你误会了我。我不主张使用ref byte [];我主张为numBytesRead使用ref int。我告诉你摆脱阵列上的固定,并在读取操作期间使用GCHandle将其固定在内存中。 – Reilly
他为什么要摆脱固定?固定更适合本地化使用(只要您可以使用不安全的上下文)。 GCHandle更适合在固定块不能使用的情况下持久使用。 –