سؤال

[DllImport("kernel32.dll", SetLastError=true)]
    public static extern unsafe bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);

أقوم بتنفيذ هذا من خلال طريقة كتابة (..) بتوقيع:

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

كما تعلمت من خلال النظر في هذا (تمت مناقشة استخدام نظير القراءة) أحتاج إلى تنفيذ حلقات أثناء وجود حلقة في التعليمات البرمجية لأن كتابة / قراءة المخزن المؤقت قد لا تمر في إحدى الذهاب. هذا هو المكان الذي تبدأ المشكلة:

إذا كنت ترغب في الحفاظ على توقيع طريقة C # الخاصة بي لقبول الفراغ *، على عكس مثال المقروء المرتبط حيث يتم قبول البايت * كمعلمة للمؤخرة.

هذا يعني أنه بعد تمريرة واحدة من FeadFile، يجب أن أتحرك الفراغ الخاص بي * إلى جانب بداية المخزن المؤقت الذي لم يكتب بعد. لا أستطيع أن أقوم بذلك على ما يبدو من خلال زيادة الفراغية فقط * مع uint الذي يحمل عدد البايتات المكتوبة ... أفهم أن الفراغ * ليس لديه حجم محدد مسبقا وهذا الزيادة غير ممكن ولكن أتساءل كيف يجب أن تحقق ما أحاول أن أفعل.

هل كانت مفيدة؟

المحلول

يجب أن تكون قادرا على الإدلاء buffer إلى أ byte* ثم زيادة ذلك. لم يكن لديه مؤشر الفراغ الحجم المرتبط به الأمر كذلك إذا كنت تريد نقل إنه عدد معين من البايتات في أي اتجاه يمكنك إلقاءه على نوع مختلف من المؤشر (أي نوع لهذه المسألة) ثم استخدم حجم النوع المصبوب في الحساب المؤشر، مثل ذلك:

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

يلقي الخط أعلاه buffer إلى مؤشر البايت، ثم تزيد موقفها من قبل wrtn عدد البايتات ثم يلقي المؤشر الجديد مرة أخرى إلى الفراغ *. بالطبع، صب إلى 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* لأنه سيجعله متوافقا مع المتصلين الآخرين من C # و byte* يجعل أكثر منطقية في هذه الحالة. لا يجب أن تقلق بشأن جعله يتطابق مع توقيع واجهة برمجة تطبيقات WriteFile الأصلية لأنك يمكن أن يلقي byte* كما هو موضح أعلاه إلى 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 # باستخدام العديد من الفئات الموجهة نحو الدفق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top