2016-05-23 17 views
3

In unserem C++ - Projekt unter MacOS X, verwenden wir stdio für die Interaktion mit Clients. Die von uns verwendete Dylib verwendet jedoch auch stdio, um "offene Protokolldateien" zu drucken. Dadurch wird die gesamte Kommunikation zwischen unseren Kunden und der Anwendung unterbrochen. Ich habe mir die Beispiele angesehen, wie man stdio in eine Datei umleitet oder stdio vorübergehend deaktiviert. Aber wir konnten es nicht schaffen.C++ Redirect oder deaktivieren Sie stdio vorübergehend

Also, wie können wir stdio während der Interaktion mit der Dylib vorübergehend deaktivieren oder umleiten.

Antwort

1
void RedirectStandardStreamsToDEVNULL(int *_piOriginalSTDIN_FILENO, int *_piOriginalSTDOUT_FILENO, int *_piOriginalSTDERR_FILENO) 
{ 
     //flushing pending things before redirection. 
     //fflush(stdin); 
     fflush(stdout); 
     fflush(stderr); 

     *_piOriginalSTDIN_FILENO = dup(STDIN_FILENO); 
     *_piOriginalSTDOUT_FILENO = dup(STDOUT_FILENO); 
     *_piOriginalSTDERR_FILENO = dup(STDERR_FILENO); 

     int devnull = open("/dev/null", O_RDWR); 
     dup2(devnull, STDIN_FILENO); 
     dup2(devnull, STDOUT_FILENO); 
     dup2(devnull, STDERR_FILENO); 
     close(devnull); 
} 
void RestoreStandardStreams(int *_piOriginalSTDIN_FILENO, int *_piOriginalSTDOUT_FILENO, int *_piOriginalSTDERR_FILENO) 
{ 
     //flushing pending things before restoring. 
     //fflush(stdin); 
     fflush(stdout); 
     fflush(stderr); 

     dup2(*_piOriginalSTDIN_FILENO, STDIN_FILENO); 
     dup2(*_piOriginalSTDOUT_FILENO, STDOUT_FILENO); 
     dup2(*_piOriginalSTDERR_FILENO, STDERR_FILENO); 
} 

void myfunction() 
{ 
    int iOriginalSTDIN_FILENO = -1; 
    int iOriginalSTDOUT_FILENO = -1; 
    int iOriginalSTDERR_FILENO = -1; 
    RedirectStandardStreamsToDEVNULL(&iOriginalSTDIN_FILENO, &iOriginalSTDOUT_FILENO, &iOriginalSTDERR_FILENO); 

//all of your code which prints to stdout or stderr will be directed to /dev/null 

    RestoreStandardStreams(&iOriginalSTDIN_FILENO, &iOriginalSTDOUT_FILENO, &iOriginalSTDERR_FILENO); 

} 

wichtiger Punkt ist, um die Funktionen zu identifizieren, die innerhalb dylib aus dem Code aufgerufen werden. Umgeben Sie nun solche Funktionen mit den oben beschriebenen Redirect- und Restore-Funktionen.

+0

Danke selbeerk, wir haben die Lösung ausprobiert. Uns ist aufgefallen, dass beim ersten Ausführen des Codes der Text "Protokolldateien öffnen" von der Konsole verschwindet. Aber das nächste Mal bleibt es und stürzt die Kommunikation mit der Client-App ab. Ich denke, Ihr Ansatz behandelt alle drei Fälle von stdio-Nutzung; also habe ich erwartet, dass es funktionieren würde. – barbarossa

+0

Wenn ich 'close (STDOUT_FILENO);' oder 'fclose (stdout);' schreibe, wird der Protokolltext nie gedruckt. Gibt es eine Möglichkeit, stdout danach wiederherzustellen? – barbarossa

+0

'dup2' selbst schließt das STDOUT_FILENO innerhalb der Redirect-Funktion. Verschachteln Sie den gesamten Aufruf von dylib unter 'Redirect' und' Restore' richtig? – sameerkn

2

OSX ist ein POSIX-System, und wie bei allen POSIX-Systemen ist die Standardausgabe der Dateideskriptor STDOUT_FILENO (ein Makro, das als 1 definiert ist).

Was Sie tun können, ist duplicateSTDOUT_FILENO auf eine andere Datei-Descriptor, open eine temporäre Datei und duplizieren (mit dup2) die temporäre Datei als STDOUT_FILENO. Dann, wann immer es ausgegeben wird zu Standard out (mit einfachem write, C printf oder C++ std::cout) wird es in die temporäre Datei eingefügt.

Wenn Sie mit der vorübergehenden "Umleitung" fertig sind, duplizieren Sie einfach die gespeicherte Standardausgabe (vom ersten dup Aufruf) zurück in STDOUT_FILENO. und schließen und entfernen Sie die temporäre Datei.

Etwas wie folgt aus:

int saved_stdout = dup(STDOUT_FILENO); 

int temp_file = open("/tmp/temp_stdout", O_WRONLY, 0600); 
dup2(temp_file, STDOUT_FILENO); // Replace standard out 

// Code here to write to standard output 
// It should all end up in the file /tmp/temp_stdout 

dup2(saved_stdout, STDOUT_FILENO); // Restore old standard out 
close(temp_file) 
unlink("/tmp/temp_stdout"); // Remove file 
+0

Danke Joachim, wir haben deinen Vorschlag ausprobiert. Leider druckt es immer noch "offene Protokolldateien" an das stdio. – barbarossa