Domanda

Sto avvolgendo il codice C++ esistente da a BSD project nel nostro wrapper personalizzato e voglio integrarlo nel nostro codice con il minor numero di modifiche possibile.Questo codice utilizza fprintf su cui stampare stderr per registrare/segnalare errori.

Voglio reindirizzarlo in un posto alternativo all'interno dello stesso processo.SU Unix L'ho fatto con a socketpair e un thread:un'estremità della presa è dove invio stderr (tramite una chiamata a dup2) e l'altra estremità viene monitorata in un thread, dove posso quindi elaborare l'output.

Questo non funziona finestre tuttavia perché un socket non è la stessa cosa di un handle di file.

Tutti i documenti che ho trovato sul Web mostrano come reindirizzare l'output di un processo figlio, che non è quello che voglio.Come posso reindirizzare stderr all'interno dello stesso processo ottenendo un callback di qualche tipo quando viene scritto l'output?(e prima che tu lo dica, ci ho provato SetStdHandle ma non riesco a trovare alcun modo per farlo funzionare)...

È stato utile?

Soluzione

Puoi utilizzare una tecnica simile su Windows, devi solo usare parole diverse per gli stessi concetti.:) Questo articolo: http://msdn.microsoft.com/en-us/library/ms682499.aspx utilizza una pipe win32 per gestire l'I/O da un altro processo, devi semplicemente fare la stessa cosa con i thread all'interno dello stesso processo.Naturalmente, nel tuo caso tutto l'output su stderr da qualsiasi punto del processo verrà reindirizzato al tuo consumatore.

In realtà, altri pezzi del puzzle di cui potresti aver bisogno lo sono _fdopen E _open_osfhandle.In effetti, ecco un esempio correlato tratto da alcuni codice Anni fa ho pubblicato:

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

In questo caso, il processo principale era un processo GUI che non inizia affatto con gli handle stdio.Apre una console, quindi inserisce gli handle giusti in stdout e stdin in modo che la funzione debug() (che è stata progettata come funzione interattiva stdio) possa interagire con la console appena creata.Dovresti essere in grado di aprire alcune pipe e fare lo stesso genere di cose per reindirizzare stderr.

Altri suggerimenti

Devi ricordare che ciò che MSVCRT chiama "handle del sistema operativo" non sono handle Win32, ma un altro livello di handle aggiunto solo per confonderti.MSVCRT tenta di emulare i numeri di handle Unix dove stdin = 0, stdout = 1, stderr = 2 e così via.Gli handle Win32 sono numerati in modo diverso e i loro valori sono sempre multipli di 4.Aprire il tubo e configurare correttamente tutte le maniglie richiederà di sporcarsi le mani.L'utilizzo del codice sorgente MSVCRT e di un debugger è probabilmente un requisito.

Dici che non vuoi usare una pipe denominata per uso interno;probabilmente vale la pena sottolineare che la documentazione per CreaPipe() stati, "Le pipe anonime vengono implementate utilizzando una pipe denominata con un nome univoco.Pertanto, è spesso possibile passare un handle a una pipe anonima a una funzione che richiede un handle a una pipe denominata." Quindi, ti suggerisco di scrivere semplicemente una funzione che crei una pipe simile con le impostazioni corrette per la lettura asincrona.Tendo a utilizzare un GUID come stringa (generata utilizzando CoCreateGUID() E StringFromIID()) per darmi un nome univoco e quindi creare le estremità server e client della pipe denominata con le impostazioni corrette per I/O sovrapposto (maggiori dettagli su questo e sul codice, qui: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).

Una volta ottenuto ciò, collego del codice che devo leggere un file utilizzando I/O sovrapposto con una porta di completamento I/O e, beh, ricevo solo notifiche asincrone dei dati non appena arrivano...Tuttavia, ho una discreta quantità di codice di libreria ben testato che fa sì che tutto ciò accada...

Probabilmente è possibile impostare la pipe denominata e quindi eseguire semplicemente una lettura sovrapposta con un evento nel file your OVERLAPPED struttura e controlla l'evento per vedere se i dati erano disponibili...Tuttavia non ho alcun codice disponibile che lo faccia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top