[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开发者_如何学Go 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.
You should be able to cast buffer
to a byte*
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:
buffer = (void *)((byte*)buffer + wrtn);
The line above casts buffer
to a byte pointer, then increments its position by wrtn
number of bytes and then casts the new pointer back to a void*. Of course, casting to a byte*
is the obvious choice if you are wanting to perform arbitrary pointer arithmetic.
Another possibility is to treat buffer
as a byte*
all along and only cast it to void*
when you pass it to 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;
}
}
And, as a last suggestion, I would consider changing the signature of Write
altogether to use a byte*
instead of void*
because it would make it more compatible with other callers from C# and a byte*
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 the byte*
as shown above to a void*
when passing it in.
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;
}
}
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.
精彩评论