Windows C ++: Cum pot redirecționa stderr pentru apelurile către fprintf?

Am înfășurat codul C ++ existent dintr-un proiect BSD în propriul nostru pachet personalizat și vreau să îl integrez în codul nostru cu cât mai puține modificări posibil. Acest cod folosește fprintf pentru a imprima pe stderr pentru a loga/raporta erorile.

Vreau să redirecționez acest lucru într-un loc alternativ în cadrul aceluiași proces. Pe Unix am făcut acest lucru cu un socketpair și un thread : un capăt al soclului este locul unde trimit stderr (prin intermediul unui apel la dup2 ) iar celălalt capăt este monitorizat într-un fir, unde pot apoi să procesez ieșirea.

Acest lucru nu funcționează la Windows , deși un soclu nu este același ca un mâner de fișiere.

Toate documentele pe care le-am găsit pe web arată cum să redirecționați ieșirea dintr-un proces copil, ceea ce nu este ceea ce vreau. Cum pot redirecționa stderr în cadrul aceluiași proces, obținând un apel invers într-o anumită ordine când se scrie semnalul de ieșire? (și înainte de a spune așa, am încercat SetStdHandle , dar nu pot găsi nici o modalitate de a face acest lucru) ...

0
fr hi bn

3 răspunsuri

Puteți utiliza o tehnică similară pe Windows, trebuie doar să utilizați cuvinte diferite pentru aceleași concepte. :) Acest articol: http://msdn.microsoft.com/en-us/ biblioteca/ms682499.aspx utilizează o conductă win32 pentru a manipula I/O dintr-un alt proces, trebuie să faci același lucru cu fire în cadrul aceluiași proces. Bineînțeles, în cazul tău, tot ce iese la stderr de oriunde în proces va fi redirecționat către consumatorul tău.

De fapt, alte piese de puzzle de care ai putea avea nevoie sunt _fdopen și _open_osfhandle . De fapt, iată un exemplu asemănător din cod pe care l-am lansat acum câțiva ani:

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

În acest caz, procesul principal a fost un proces GUI care nu pornește deloc cu mânere stdio. Acesta deschide o consolă, apoi împinge mânerele drepte în stdout și stdin astfel încât funcția debug() (care a fost proiectată ca o funcție interactivă stdio) poate interacționa cu consola nou creată. Ar trebui să puteți deschide niște țevi și să faceți același lucru pentru a redirecționa stderr.

0
adăugat

Trebuie să vă amintiți că ceea ce MSVCRT numește "mânerele OS" nu sunt mânere Win32, dar un alt strat de mânere adăugat doar pentru a vă confunda. MSVCRT încearcă să emuleze numerele de mâini Unix unde stdin = 0, stdout = 1, stderr = 2 și așa mai departe. Mânerele Win32 sunt numerotate în mod diferit, iar valorile lor se întâmplă întotdeauna să fie multiple de 4. Deschiderea țevii și obținerea tuturor mânerelor configurate corespunzător va necesita obtinerea de mâini murdare. Utilizarea codului sursă MSVCRT și a unui program de depanare este probabil o cerință.

0
adăugat

Menționați că nu doriți să utilizați o țeava numită pentru uz intern; probabil merită să subliniem că documentația pentru CreatePipe() <, "țevile anonime sunt implementate folosind o conductă numită cu un nume unic. De aceea, puteți trece adesea un mâner la o conductă anonimă unei funcții care necesită un mâner pentru o conductă numită." > Deci, vă sugerez să scrieți doar o funcție care creează o conductă similară cu setările corecte pentru citirea asincronă. Tind să folosesc un GUID ca un șir (generat folosind CoCreateGUID() și StringFromIID() ) pentru a-mi da un nume unic și apoi să creez serverul și clientul numită țeavă cu setările corecte pentru I/O suprapuse (mai multe detalii despre acest lucru și codul, aici: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html ).

Odată ce am făcut că am sârmă de până un cod pe care trebuie să citesc un fișier folosind I/O suprapuse cu un I/O Completion Port și, bine, atunci am primit notificări async a datelor în care acesta sosește ... Cu toate acestea, eu "Am primit o cantitate corectă de cod de bibliotecă bine testat acolo, care face ca totul să se întâmple ...

Este posibil să configurați conducta numită și apoi să faceți o citire suprapusă cu un eveniment în structura OVERLAPPED și să verificați evenimentul pentru a vedea dacă datele erau disponibile ... Nu am niciun cod disponibil, care face asta, deși.

0
adăugat