0
[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;
    }
}

正如我通过查看本文了解到的(讨论了读取对应项的使用),我需要在我的代码中实现一个 while 循环,因为缓冲区的写入/读取可能不会一次性完成。这是问题开始的地方:

如果我想保留我的 C# 方法签名以接受 void*,这与链接的读取示例不同,其中字节 * 被接受为缓冲区的参数。

这意味着在通过 WriteFile 一次之后,我应该将我的 void* 移动到尚未写入的缓冲区的开头。我显然不能通过仅使用包含写入字节数的 uint 增加 void* 来做到这一点......我知道 void* 没有预定的大小,因此增加是不可能的,但我想知道我应该如何实现我正在努力做。

4

1 回答 1

1

您应该能够转换buffer为 abyte*然后递增它。一个 void 指针没有与之关联的大小,所以如果你想在任何方向移动它一定数量的字节,你可以将它转换为不同类型的指针(任何类型),然后使用转换类型的大小在指针算术中,像这样:

buffer = (void *)((byte*)buffer + wrtn);

上面的行转换buffer为字节指针,然后将其位置增加wrtn字节数,然后将新指针转换回 void*。当然,byte*如果您想要执行任意指针运算,则强制转换为 a 是显而易见的选择。

另一种可能性是一直将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完全更改为使用 abyte*而不是,void*因为它会使其与 C# 的其他调用者更兼容,并且byte*在这种情况下更有意义。您不必担心使其与 WriteFile 本机 API 的签名相匹配,因为您可以在传入时将byte*如上所示的转换为 a 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;
    }
}

唉,我不得不同意其中一位评论者的观点。你为什么做这个?有更好的方法可以使用许多面向流的类在 c# 中完成文件写入。

于 2009-11-02T14:23:02.827 回答