Межплатформенная совместимость dprintf

Linux имеет эту хорошую функцию dprintf:

Функции dprintf() и vdprintf() (как найдено в glibc2 библиотеке), точные аналоги fprintf() и vfprintf(), за исключением того, что они производят к дескриптору файла fd вместо к данному потоку.

однако, поскольку тот же самый источник указывает:

Эти функции являются расширениями GNU, не в C или POSIX. Очевидно, имена были плохо выбраны. Многим системам (как MacOS) назвали несовместимые функции dprintf(), обычно некоторая отладочная версия printf(), возможно, с прототипом как

void dprintf (int level, const char *format, ...);

где первый параметр является уровнем отладки (и вывод к stderr). Кроме того, dprintf() (или DPRINTF) также популярное макро-название отладки printf. Так, вероятно, лучше избежать, чтобы эта функция в программах намеревалась быть портативной.

Мой вопрос

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

#ifdef SOMETHING
    #define Dprintf dprintf
#else
    #error "no dprintf"
#endif

но я не знаю что SOMETHING должен быть. Я предполагаю, что мог ограничить его просто Linux, но я мог сделать это более свободным?

5
задан kay 6 March 2017 в 19:25
поделиться

3 ответа

выглядит как DPRINTF () на самом деле в POSIX.1-2008 (с требуемым семантикой), чтобы вы могли сделать это:

#if !defined(__GLIBC__) && _POSIX_C_SOURCE < 200809
#error "dprintf may not exist, or may be wrong"
#endif

__ GLIBC __ определяется, если вы используете систему сборки GNU. Это, вероятно, так же безопасно, как вы можете быть без написания небольшой тестовой программы.

9
ответ дан 18 December 2019 в 11:56
поделиться

Вы можете сделать тест AutoConf, если вы используете AutoTools для вашей BuildSystem.

AC_LANG([C])
AC_USE_SYSTEM_EXTENSIONS
AC_ARG_WITH([dprintf],
  [AS_HELP_STRING([--with-dprintf],
    [Assume that dprintf prints to a specified file descriptor])],
  [], [with_dprintf=check])
AS_IF([test "x$with_dprintf" = xcheck],
  [AC_RUN_IFELSE(
    [AC_LANG_PROGRAM([[
        #include <stdio.h>
        #include <string.h>
        int debug_level;
      ]], [[
        char msg[] = "Hello, world!\n";
        char rcv[sizeof(msg)] = "";
        FILE *f = tmpfile();
        int fd = fileno(f);
        debug_level = fd - 1;
        dprintf(fd, "%s", msg);
        fseek(f, 0, SEEK_SET);
        fread(rcv, 1, sizeof(msg), f);
        return strcmp(msg, rcv);
      ]]
    )], [with_dprintf=yes])])
AS_IF([test "x$with_dprintf" = xyes],
  [AC_DEFINE([HAVE_DPRINTF], [1],
    [dprintf prints to a specified file descriptor])])

(позволяя - с деплинфом или - без креннф , когда кросс-компиляция, как AC_RUN_IFELSE недействителен в этих случаях. )


FDOPEN не в стандарте C, но это в в POSIX.2, а затем. Я не вспоминаю ни одного Unix, который не имеет этого - черт, даже окна есть.

int fdprintf(int fd, char *fmt, ...) {
    va_list ap;
    FILE *f = fdopen(fd);
    int rc;

    va_start(ap, &fmt);
    rc = vfprintf(f, fmt, ap);
    fclose(f);
    va_end(ap);
    return rc;
}

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

4
ответ дан 18 December 2019 в 11:56
поделиться

Одной из основных причин Выбор приходит в последний раз, является создание работы IntelliSense. Приведя источник последовательности в первую очередь (от оператора), Intellisense может работать должным образом.

-121--1422465-

Тест AutoConf может проверить, является ли DPRINTF (1, «Blablabla») [11655] , и DPRINTF (-1, «BLABLABLA») неиспользуется интересным способом или пишет на Стдерр.

Если LIBC дает вам неправильно DPRINTF () , вы могли бы реализовать его сверху SNPRINTF () (или даже лучше ASPRINTF () ) и Написать () . И затем упомяните свой «DPRINTF.O» к линкеру, чтобы он предпочитал вас на LIBC.

Если вы хотите лучшее имя, я предлагаю FDPrintF () .

2
ответ дан 18 December 2019 в 11:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: