[DllImport("kernel32.dll", SetLastError=true)]
public static extern unsafe bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
我通过带有签名的Write(..)方法实现这个:
Write(IntPtr handleFile, void* bufferData, uint length){
void* buffer = bufferData
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
// THIS DOESNT WORK!
// I want to move along the buffer to be able to write its remainder...
// I tried many variations of this as well, but it seems even '+' is not valid for a void*
buffer += wrtn;
len -= wrtn;
}
}
正如我通过查看this (the use of the read counterpart is discussed)所学到的,我需要在我的代码中实现一个while循环,因为缓冲区的写入/读取可能不会一次完成。这就是问题的开始:
如果我想保持我的C#方法签名接受void *,不像链接的Read示例,其中字节*被接受作为缓冲区的参数。
这意味着在WriteFile传递一次之后,我应该将我的void *移动到尚未写入的缓冲区的开头。我不能通过仅使用保存写入的字节数的uint来增加void *来做到这一点...我明白void *没有预定的大小,因此增量是不可能的但我不知道我怎么应该实现什么我想做。
答案 0 :(得分:1)
您应该能够将buffer
投射到byte*
,然后再增加它。 void指针没有与之关联的大小,所以如果你想移动它可以在任何方向上移动一定数量的字节,你可以将它转换为不同类型的指针(任何类型的指针)然后在指针算术中使用铸造类型的大小,如下所示:
buffer = (void *)((byte*)buffer + wrtn);
上面的行将buffer
强制转换为字节指针,然后将其位置递增wrtn
个字节数,然后将新指针强制转换为void *。当然,如果你想要执行任意指针运算,那么转换为byte*
是显而易见的选择。
另一种可能性是将buffer
一直视为byte*
,只有在将void*
传递给WriteFile
时才将其转换为Write(IntPtr handleFile, void* bufferData, uint length)
{
byte* buffer = (byte*)bufferData;
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, (void*)buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
buffer += wrtn;
len -= wrtn;
}
}
Write
并且,作为最后一个建议,我会考虑完全更改byte*
的签名以使用void*
而不是byte*
,因为它会使其与C#中的其他来电者更兼容在这种情况下,byte*
更有意义。您不必担心使其与WriteFile本机API的签名匹配,因为您可以在传递void*
时将Write(IntPtr handleFile, byte* bufferData, uint length)
{
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, (void*)bufferData, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
bufferData+= wrtn;
len -= wrtn;
}
}
转换为{{1}}。
{{1}}唉,我必须同意其中一位评论者的意见。你为什么做这个?那里 是使用许多面向流的类在c#中完成文件写入的更好方法。