Портативный способ положить стандартный вывод в двоичном режиме

Я пишу программы на C, используемые как cgi, которые генерируют и выводят gif-изображения. Они используются на HTML-страницах с тегами вида<img src="/cgi-bin/gifprogram.cgi?param=val&etc">где параметры строки запроса описывают изображение, которое будет сгенерировано cgi.

CG-программы, вызываемые следующим образом, отправляют свой вывод на стандартный вывод. И в этом случае вывод представляет собой изображение в формате gif, содержащее множество двоичных (непечатных) байтов. Это уже отлично работает на Unix / Linux. Но Windows, по-видимому, требует отдельного непереносимого_setmode(_fileno(stdout),_O_BINARY) вызов (и некоторые специфичные для Windows#include«S). В противном случае вы получите обычную проблему cr / lf, то есть каждому 0x0A предшествует ложный 0x0D. И это не выглядит хорошо в GIF :(

Есть ли какой-либо переносимый способ обойти эту проблему, используя стандарт C ANSI без какого-либо специфичного для платформы синтаксиса и без большого количества#ifdef что попытаться обнаружить среду компиляции Windows? Более того, некоторые компиляторы Windows, очевидно, используют_setmode(_fileno(stdout),_O_BINARY) в то время как другие используютsetmode(fileno(stdout),O_BINARY), который я также должен попытаться обнаружить.

>> << Редактировать В ответ на комментарии ...

Спасибо, парни. По-видимому, мне придется взять некоторые иначе полностью совместимые с posix / переносимые программы, и бездельничать с ними только для окон [nb, JoNaThAn: действительно, не нужно редактировать, чтобы использовать это заглавные буквы :), - мой личный стиль написания намеренно грамматически свободный.

Ниже приведено первое описание некоторых глупостей, которые я собираюсь представить. Кажется, работает, насколько я могу судить, используя Mingw. Достаточно ли, т. Е. Работает для всех или большинства других компиляторов? И нужен ли, т. Е. Какой-нибудь короткий и аккуратный / быстрый и грязный способ сделать то же самое с меньшим количеством / более читаемых строк кода?

/* ---
 * windows-specific header info
 * ---------------------------- */
#ifndef WINDOWS                 /* -DWINDOWS not supplied by user */
  #if defined(_WINDOWS) || defined(_WIN32) || defined(WIN32) \
  ||  defined(DJGPP)            /* try to recognize windows compilers */ \
  ||  defined(_USRDLL)          /* must be WINDOWS if compiling for DLL */
    #define WINDOWS             /* signal windows */
  #endif
#endif
#ifdef WINDOWS                  /* Windows opens stdout in char mode, and */
  #include <fcntl.h>            /* precedes every 0x0A with spurious 0x0D.*/
  #include <io.h>               /* So emitcache() issues a Win _setmode() */
                                /* call to put stdout in binary mode. */
  #if defined(_O_BINARY) && !defined(O_BINARY)  /* only have _O_BINARY */
    #define O_BINARY _O_BINARY  /* make O_BINARY available, etc... */
    #define setmode  _setmode
    #define fileno   _fileno
  #endif
  #if defined(_O_BINARY) || defined(O_BINARY)  /* setmode() now available */
    #define HAVE_SETMODE        /* so we'll use setmode() */
  #endif
  #if defined(_MSC_VER) && defined(_DEBUG) /* MS VC++ in debug mode */
    /* to show source file and line numbers where memory leaks occur... */
    #define _CRTDBG_MAP_ALLOC   /* ...include this debug macro */
    #include <crtdbg.h>         /* and this debug library */
  #endif
  #define ISWINDOWS 1
#else
  #define ISWINDOWS 0
#endif

И следующий соответствующий код, чтобы убедиться, что стандартный вывод находится в двоичном режиме

    #if ISWINDOWS                           /* compiling for win... */
      #ifdef HAVE_SETMODE                   /* try to use setmode()*/
        if ( setmode ( fileno (stdout), O_BINARY) /* to set stdout */
        == -1 ) /* handle error here*/ ;    /* to binary mode */
      #else                                 /* setmode not available */
        #if 1                               /* so try this...*/
          freopen ("CON", "wb", stdout);    /* freopen stdout binary */
        #else                               /* or maybe this... */
          stdout = fdopen (STDOUT_FILENO, "wb"); /*fdopen stdout binary*/
        #endif                              /* done */
      #endif                                /* " */
    #endif                                  /* " */

Вы заметите, что я пытаюсь предложить альтернативы setmode (). Хотя мое альтернативное тестирование не было успешным, я оставил синтаксис для дальнейшего использования, на случай, если некоторые из них в конечном итоге окажутся полезными.

Ответы на вопрос(0)

Ваш ответ на вопрос