将stdout置于二进制模式的便携方式

时间:2016-11-15 11:55:52

标签: c linux windows io portability

我正在编写用作生成和输出gif图像的cgi的C程序。它们在带有表单标签的HTML页面中使用 <img src="/cgi-bin/gifprogram.cgi?param=val&etc">,其中查询字符串参数描述了由cgi生成的图像。

像这样调用的C程序cgi将它们的输出发送到stdout。在这种情况下,输出是一个包含大量二进制(不可打印)字节的gif图像。这在Unix / Linux上已经运行良好。但Windows显然需要单独的非便携_setmode(_fileno(stdout),_O_BINARY)电话(以及一些特定于Windows的#include)。否则你会得到通常的cr / lf问题,即每个0x0A前面都有一个假的0x0D。这在gif中并不好看:(

是否有任何可移植的解决此问题的方法,使用ANSI标准C而没有任何特定于平台的语法,并且没有很多#ifdef内容来尝试检测Windows编译环境?此外,一些Windows编译器显然使用_setmode(_fileno(stdout),_O_BINARY)而其他人使用setmode(fileno(stdout),O_BINARY),我也必须尝试检测。{/ p>

&gt;&gt;编辑&lt;&lt; 回复评论...

谢谢,伙计们。我显然必须采取其他一些完全符合posix标准/可移植的程序,并且仅仅针对Windows使用它们[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

以后确保stdout处于二进制模式的相应代码是

    #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 个答案:

没有答案