使用动态库时如何抑制输出?

发布于 2024-10-12 22:16:23 字数 1393 浏览 5 评论 0原文

我实际上对这个问题有一个解决方案,但我想知道是否有更灵活的解决方案。

我需要使用 dlopen 将库加载到我的实用程序中,然后调用其中一个函数。

不幸的是,该函数将一大堆信息喷射到 STDOUT 上,而这是我不想要的。

我有一个不可移植的解决方案,我想知道是否有更好、更通用的解决方案可以使用。

这是我所拥有的(注意:这是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));
}

有什么建议吗?

I actually have a solution to this problem, but I'm wondering if there is a slicker one.

I have the need to load in a library to my utility using dlopen and then call one of the functions.

Unfortunately, the function spews a whole bunch of information out onto STDOUT and this I do not want.

I have a solution that is non-portable and I'm wondering if there's a better, more generic solution that I could use.

Here's what I have (NB: This is 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));
}

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

热鲨 2024-10-19 22:16:23

我有一个建议,它可以让您使用预处理器来实现可移植性,或者也许是“可移植性”。

如果您尝试类似的操作

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

(忽略其他操作系统、else case、错误指令等)
然后像以前一样重新打开文件

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

,这可能会给你你想要的。

不过我还没有在家里尝试过这个。 “nul”文件存在;请参阅Windows 中的/dev/null。您可以在“预定义的C/C++编译器宏”处获取预定义的宏。

I have a suggestion, which lets you use the preprocessor for portability, or perhaps "portability".

If you try something like

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

(ignoring other OSes, else case, error directive, etc.)
and then reopen the file as before

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

then that may give you what you want.

I haven't tried this at home, though. The "nul" file exists; see /dev/null in Windows. And you can get predefined macros at "Pre-defined C/C++ Compiler Macros".

疏忽 2024-10-19 22:16:23

您可以尝试使用 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;
}

You could try using setvbuf to set stdout to have a very large buffer and be fully buffered. Then, after every call to noisy_function, clear out the buffer before flushing it to the stream. I think this invokes undefined behavior though.

Another way would be to redirect stdout to a temp file, like with this macro 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;
}
青柠芒果 2024-10-19 22:16:23

对于 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

为我工作。

For Windows console applications:

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

Worked for me.

提笔落墨 2024-10-19 22:16:23

在 Windows 中,您也可以重定向流。
请参阅http://support.microsoft.com/kb/110930/en-us

In Windows you can redirect streams too.
See http://support.microsoft.com/kb/110930/en-us

待天淡蓝洁白时 2024-10-19 22:16:23

不幸的是,freopening 到特定于平台的空文件名大约是标准 C 中最接近的。您还可以考虑修改库本身,以免在 stdout 上输出太多输出。

也就是说,实际上,您需要担心的唯一操作系统是基于 UNIX(包括 MacOS)或 Windows - 对于 Windows,默认情况下隐藏 stdout,因此您可以跳过重定向步骤,并且对于 * nix 你已经有代码了。

Unfortunately, freopening to a platform-specific null filename is about the closest you can get in standard C. You could also consider modifying the library itself to not spew so much output on stdout.

That said, in practice, the only OSes you need to worry about are either unix-based (including MacOS) or Windows - in the case of Windows, stdout is hidden by default, so you can just skip the redirection step, and for *nix you have the code already.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文