ويندوز سي ++:كيف يمكنني إعادة توجيه stderr للمكالمات إلى fprintf؟

StackOverflow https://stackoverflow.com/questions/7664

  •  08-06-2019
  •  | 
  •  

سؤال

أقوم بتغليف كود C++ الموجود من ملف بي إس دي المشروع في غلافنا المخصص وأريد دمجه في الكود الخاص بنا مع أقل عدد ممكن من التغييرات.يستخدم هذا الرمز fprintf للطباعة ل com.stderr من أجل تسجيل / الإبلاغ عن الأخطاء.

أريد إعادة توجيه هذا إلى مكان بديل ضمن نفس العملية.على يونكس لقد فعلت هذا مع أ socketpair و أ thread:أحد طرفي المقبس هو المكان الذي أرسله com.stderr (من خلال الاتصال بـ dup2) ويتم مراقبة الطرف الآخر في خيط، حيث يمكنني بعد ذلك معالجة الإخراج.

هذا لا يعمل على شبابيك على الرغم من أن المقبس ليس هو نفسه مقبض الملف.

تُظهر جميع المستندات التي وجدتها على الويب كيفية إعادة توجيه المخرجات من عملية فرعية، وهو ما لا أريده.كيف يمكنني إعادة التوجيه com.stderr ضمن نفس العملية الحصول على رد اتصال من نوع ما عند كتابة الإخراج؟(وقبل أن تقول ذلك، لقد حاولت SetStdHandle ولكن لا يمكن العثور على أي طريقة لإنجاز هذا العمل) ...

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

المحلول

يمكنك استخدام تقنية مشابهة على نظام التشغيل Windows، ما عليك سوى استخدام كلمات مختلفة لنفس المفاهيم.:) هذا المقال: http://msdn.microsoft.com/en-us/library/ms682499.aspx يستخدم أنبوب Win32 للتعامل مع الإدخال/الإخراج من عملية أخرى، ما عليك سوى القيام بنفس الشيء مع سلاسل الرسائل ضمن نفس العملية.بالطبع، في حالتك، سيتم إعادة توجيه جميع المخرجات إلى stderr من أي مكان في العملية إلى المستهلك الخاص بك.

في الواقع، هناك قطع أخرى من اللغز قد تحتاجها _fdopen و _open_osfhandle.في الواقع، هنا مثال ذو صلة من البعض شفرة لقد اصدرت منذ سنوات:

DWORD CALLBACK DoDebugThread(void *)
{
    AllocConsole();
    SetConsoleTitle("Copilot Debugger");
    // The following is a really disgusting hack to make stdin and stdout attach
    // to the newly created console using the MSVC++ libraries. I hope other
    // operating systems don't need this kind of kludge.. :)
    stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
    stdin->_file  = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
    debug();
    stdout->_file = -1;
    stdin->_file  = -1;
    FreeConsole();
    CPU_run();
    return 0;
}   

في هذه الحالة، كانت العملية الرئيسية عبارة عن عملية واجهة المستخدم الرسومية والتي لا تبدأ بمقابض stdio على الإطلاق.فهو يفتح وحدة التحكم، ثم يدفع المقابض اليمنى إلى stdout وstdin حتى تتمكن وظيفة debug() (التي تم تصميمها كوظيفة تفاعلية stdio) من التفاعل مع وحدة التحكم المنشأة حديثًا.يجب أن تكون قادرًا على فتح بعض الأنابيب والقيام بنفس الشيء لإعادة توجيه ملف stderr.

نصائح أخرى

عليك أن تتذكر أن ما يسميه MSVCRT "مقابض نظام التشغيل" ليس مقابض Win32، بل تمت إضافة طبقة أخرى من المقابض لإرباكك.يحاول MSVCRT محاكاة أرقام مقبض Unix حيث stdin = 0, stdout = 1, stderr = 2 وهكذا.يتم ترقيم مقابض Win32 بشكل مختلف وتكون قيمها دائمًا من مضاعفات الرقم 4.سيتطلب فتح الأنبوب وتهيئة جميع المقابض بشكل صحيح جعل يديك فوضوية.من المحتمل أن يكون استخدام كود مصدر MSVCRT ومصحح الأخطاء أحد المتطلبات.

لقد ذكرت أنك لا تريد استخدام توجيه الإخراج المسمى للاستخدام الداخلي؛ربما يكون من المفيد الإشارة إلى أن الوثائق الخاصة بـ كريتبيبي() تنص على، "يتم تنفيذ توجيهات الإخراج المجهولة باستخدام توجيه إخراج مسمى باسم فريد.لذلك، يمكنك غالبًا تمرير مؤشر إلى أنبوب مجهول إلى وظيفة تتطلب مؤشرًا إلى أنبوب مسمى." لذا، أقترح عليك أن تكتب فقط دالة تنشئ أنبوبًا مشابهًا بالإعدادات الصحيحة للقراءة غير المتزامنة.أميل إلى استخدام GUID كسلسلة (تم إنشاؤها باستخدام CoCreateGUID() و StringFromIID()) لإعطائي اسمًا فريدًا ثم إنشاء طرفي الخادم والعميل للأنبوب المسمى باستخدام الإعدادات الصحيحة للإدخال/الإخراج المتراكب (مزيد من التفاصيل حول هذا الأمر والتعليمات البرمجية هنا: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).

بمجرد أن أقوم بتوصيل بعض التعليمات البرمجية التي يجب أن أقرأها ملفًا باستخدام الإدخال/الإخراج المتداخل مع منفذ إكمال الإدخال/الإخراج، حسنًا، بعد ذلك أحصل على إشعارات غير متزامنة للبيانات عند وصولها...ومع ذلك، لدي قدر لا بأس به من أكواد المكتبة التي تم اختبارها جيدًا هناك والتي تجعل كل ذلك يحدث...

ربما يكون من الممكن إعداد الأنبوب المسمى ثم إجراء قراءة متداخلة مع حدث في ملفك OVERLAPPED هيكلة والتحقق من الحدث لمعرفة ما إذا كانت البيانات متاحة...ليس لدي أي كود متاح يفعل ذلك بالرغم من ذلك.

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