Как подавить вывод при использовании динамической библиотеки? - PullRequest
5 голосов
/ 21 января 2011

У меня на самом деле есть решение этой проблемы, но мне интересно, есть ли более гладкий.

Мне нужно загрузить библиотеку в мою утилиту, используя dlopen, а затем вызовите одну из функций.

К сожалению, функция выдает целую кучу информации на STDOUT, а этого я не хочу.портативный, и мне интересно, есть ли лучшее, более общее решение, которое я мог бы использовать.

Вот что у меня есть ( NB : Это C):

/*
 * Structure for retaining information about a stream, sufficient to
 * recreate that stream later on
 */
struct stream_info {
    int fd;
    fpos_t pos;
};
#define STDOUT_INFO 0
#define STDERR_INFO 1

struct stream_info s_info[2];
point_stream_to_null(stdout, &s_info[STDOUT_INFO]);
point_stream_to_null(stderr, &s_info[STDERR_INFO]);

void *output = noisy_function();

reset_stream(stderr, &s_info[STDERR_INFO]);
reset_stream(stdout, &s_info[STDOUT_INFO]);

/*
 * Redirects a stream to null and retains sufficient information to restore the stream to its original location
 *** NB ***
 * Not Portable
 */
void point_stream_to_null(FILE *stream, struct stream_info *info) {
    fflush(stream);
    fgetpos(stream, &(info->pos));
    info->fd = dup(fileno(stream));
    freopen("/dev/null", "w", stream);
}

/*
 * Resets a stream to its original location using the info provided
 */
void reset_stream(FILE *stream, struct stream_info *info) {
    fflush(stream);
    dup2(info->fd, fileno(stream));
    close(info->fd);
    clearerr(stream);
    fsetpos(stream, &(info->pos));
}

Есть предложения?

Ответы [ 5 ]

2 голосов
/ 29 марта 2011

У меня есть предложение, которое позволяет вам использовать препроцессор для переносимости или, возможно, «переносимости».

Если вы попробуете что-то вроде

#if defined __unix__
#define DEVNULL "/dev/null"
#elif defined _WIN32
#define DEVNULL "nul"
#endif

(игнорирование других ОС, в другом случае, директива об ошибке и т. Д.) а затем снова откройте файл как раньше

FILE *myfile = freopen(DEVNULL, "w", stream);

тогда это может дать вам то, что вы хотите.

Хотя я не пробовал это дома. Файл "nul" существует; смотрите / dev / null в Windows . И вы можете получить предопределенные макросы в «Предопределенные макросы компилятора C / C ++» .

2 голосов
/ 21 января 2011

Вы можете попробовать использовать setvbuf для установки stdout, чтобы иметь очень большой буфер и быть полностью буферизованным.Затем после каждого вызова noisy_function очищайте буфер перед его сбросом в поток.Я думаю, что это вызывает неопределенное поведение.

Другим способом было бы перенаправить стандартный вывод во временный файл, как с этой функцией макроса.

#include <stdio.h>

#define QUIET_CALL(noisy) { \
    FILE* tmp = stdout;\
    stdout = tmpfile();\
    (noisy);\
    fclose(stdout);\
    stdout = tmp;\
}

int main(){
    QUIET_CALL(printf("blah blah"));
    printf("bloo bloo\n");
    return 0;
}
0 голосов
/ 22 февраля 2019

Для консольных приложений Windows:

freopen("NUL", "w", stdout); // redirect stdout to the windows version of /dev/null
NoisyDllFunction();
freopen("CON", "w", stdout); // redirect stdout back to the console

работал для меня.

0 голосов
/ 21 января 2011

К сожалению, возможность свободного доступа к пустому имени файла для конкретной платформы примерно равна тому, который вы можете получить в стандартном языке C. Вы можете также рассмотреть возможность изменения самой библиотеки, чтобы не выкидывать столько вывода на стандартный вывод.

При этомна практике единственные операционные системы, о которых вам нужно беспокоиться, это либо Unix (включая MacOS), либо Windows - в случае Windows stdout по умолчанию скрыт, так что вы можете просто пропустить шаг перенаправления, а для * nix у вас естькод уже.

0 голосов
/ 21 января 2011

В Windows вы также можете перенаправлять потоки.Смотри http://support.microsoft.com/kb/110930/en-us

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...