实现 Win32 文件写入
[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(讨论了读取对应项的使用) 我需要在代码中实现一个 while 循环,因为缓冲区的写入/读取可能不会一次性完成。这就是问题开始的地方:
如果我想保留我的 C# 方法签名以接受 void*,与链接的 Read 示例不同,其中接受 byte* 作为缓冲区的参数。
这意味着在一次 WriteFile 传递之后,我应该将 void* 移动到尚未写入的缓冲区的开头。我显然不能通过仅用保存写入字节数的 uint 递增 void* 来做到这一点...我知道 void* 没有预定的大小,因此递增是不可能的,但我想知道我应该如何实现什么我正在努力做。
[DllImport("kernel32.dll", SetLastError=true)]
public static extern unsafe bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
I am implementing this through a Write(..) method with a signature:
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;
}
}
As I learned by looking at this (the use of the read counterpart is discussed) I need to implement a while loop in my code because the write/read of the buffer might not go through in one go. This is where the problem start:
If I want to keep my C# method signature as to accept a void*, unlike the linked Read example where a byte* is accepted as a parameter for the buffer.
This means that after one pass of the WriteFile, I should move my void* along to the start of the buffer that has not been written yet. I cannot apparently do this by just incrementing void* with the uint that holds the number of bytes written... I understand that void* does not have a predetermined size and that incrementing is therefore not possible but I wonder how I then should achieve what I am trying to do.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您应该能够将
buffer
转换为byte*
,然后递增它。 void 指针没有与其关联的大小,因此如果您想在任何方向移动它一定数量的字节,您可以将其转换为不同类型的指针(与此相关的任何类型)然后在指针算术中使用转换类型的大小,如下所示:上面的行将
buffer
转换为字节指针,然后将其位置增加wrtn
字节数,然后将新指针强制转换回 void*。当然,如果您想要执行任意指针算术,则转换为byte*
是显而易见的选择。另一种可能性是始终将
buffer
视为byte*
,并且仅在将其传递给WriteFile< 时将其强制转换为
void*
/code>并且,作为最后一个建议,我会考虑完全更改
Write
的签名以使用byte*
而不是void*
因为它会使其与 C# 中的其他调用者更加兼容,并且在这种情况下byte*
更有意义。您不必担心使其与 WriteFile 本机 API 的签名相匹配,因为您可以在传入时将上面所示的byte*
转换为void*
唉,我不得不同意一位评论者的观点。你为什么要这样做?那里
是使用许多面向流的类在 C# 中完成文件写入的更好方法。
You should be able to cast
buffer
to abyte*
and then increment it. A void pointer doesn't have size associated with it so if you want to move it a certain number of bytes in any direction you can cast it to a different type of pointer (any type for that matter) and then use the casted type's size in the pointer arithmetic, like so:The line above casts
buffer
to a byte pointer, then increments its position bywrtn
number of bytes and then casts the new pointer back to a void*. Of course, casting to abyte*
is the obvious choice if you are wanting to perform arbitrary pointer arithmetic.Another possibility is to treat
buffer
as abyte*
all along and only cast it tovoid*
when you pass it toWriteFile
And, as a last suggestion, I would consider changing the signature of
Write
altogether to use abyte*
instead ofvoid*
because it would make it more compatible with other callers from C# and abyte*
makes more sense in that case. You shouldn't have to worry about making it match the signature of the WriteFile native API since you can cast thebyte*
as shown above to avoid*
when passing it in.Alas, I have to agree with one of the commenters. Why are you doing this? There
are better ways to accomplish a file write in c# using many of the stream oriented classes.