2016-05-23 2 views
3

В нашем проекте на C++ под MacOS X мы используем stdio для взаимодействия с клиентами. Тем не менее, используемый нами dylib также использует stdio для печати «открытых файлов журнала». Это нарушает все коммуникации между нашими клиентами и приложением. Я рассмотрел примеры перенаправления stdio в файл или временное отключение stdio. Но в этом мы не смогли бы добиться успеха.C++ перенаправить или отключить stdio временно

Итак, как мы можем временно отключить или перенаправить stdio во время взаимодействия с dylib.

ответ

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

} 

Важным моментом является то, чтобы определить функции, которые вызываются внутри dylib из вашего кода. Теперь объедините такие функции с функциями перенаправления и восстановления, описанными выше.

+0

Спасибо, что мы попробовали решение. Мы заметили, что при первом запуске кода текст «open log files» исчезает с консоли. Но в следующий раз он остается и прерывает связь с клиентским приложением. Я думаю, что ваш подход обрабатывает все три случая использования stdio; поэтому я ожидал, что это сработает. – barbarossa

+0

Кроме того, если я пишу 'close (STDOUT_FILENO);' или 'fclose (stdout);' текст журнала никогда не печатается. Есть ли способ восстановить stdout позже? – barbarossa

+0

'dup2' сам делает закрытие STDOUT_FILENO внутри функции« Перенаправление ». Правильно ли вы вложили весь вызов в dylib под функциями «Переадресация» и «Восстановить»? – sameerkn

2

OSX - это POSIX-системы, и, как и все стандартные системы POSIX, выходной файл представляет собой дескриптор файла STDOUT_FILENO (который является макросом, определяемым как 1).

Что вы можете сделать, это duplicateSTDOUT_FILENO на другой файловый дескриптор, open временный файл и тиражирование (используя dup2) временный файл как STDOUT_FILENO. Тогда всякий раз, когда есть выход для стандартного вывода (используя простой write, C printf или C++ std::cout), он будет помещен во временный файл.

Когда выполняется временное перенаправление, вы просто дублируете сохраненный стандартный вывод (с первого вызова dup) обратно в STDOUT_FILENO. и закрыть и удалить временный файл.

Что-то вроде следующего:

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

Спасибо, Joachim, мы попробовали ваше предложение. К сожалению, он все еще печатает «открытые файлы журналов» в stdio. – barbarossa

Смежные вопросы