我可以用malloc和隐式转换替换对open_memstream的调用吗?

Spe*_*bun 6 c windows malloc stream

所有,

我有一个打印到流的程序.我需要在内存中缓冲此流,然后根据需要将每行打印到实际文件中.

由于fprintf()函数调用必须有一个FILE *指针,我需要在内存中使用所述指针寻址空间.我曾使用过该open_memstream()功能,但Windows不支持此功能.

因为malloc()返回一个void *指针,根据需要神奇地转换为必要的指针,我可以使用它作为我的FILE *指针吗?如果是这样,有什么警告?我需要注意空间不足吗?

更新:

在找到了open_memstream()比它应该更难的源之后,看起来他们正在为malloc空间做一个文件流.

既然如此,我已经得到了它们的来源,如果我无法通过mingw获得与Windows交叉编译的工作版本,我将会讨论.

Spe*_*bun 6

对于那些追随我的人,有希望!有一个解决方案.正如我的问题所述,我正在使用open_memstream(),这在Windows上是不受支持的.

由于我有一个File *指针(这不能改为char *),我需要将它重定向到内存,直到以后.因为我正在处理内存中的文件,所以我调查了一下mmap().它轻松地解决了这个问题,但同样,它只是linux.

但是,windows包括一个mmap()被称为的推论MapViewOfFile().通过#ifdef我的魔力,我已经使用任何必要的:

#ifdef WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
Run Code Online (Sandbox Code Playgroud)

稍后,在main方法中,我调用tmpfile()两个平台都支持的方法.这将为我打开一个保证唯一临时文件的流.既然我有FILE *指针,我需要mmap()空间.但是mmap()需要文件描述符而不是流,所以我使用该fileno()函数来获取新的文件描述符.

/* create tmp file and get file descriptor */
int fd;
yyout = tmpfile();
fd = fileno(yyout);
Run Code Online (Sandbox Code Playgroud)

现在我有一些#ifdef代码来确定需要使用哪个内存映射代码集.请注意两个版本之间的映射空间的差异.Windows地图16384 bytes和linux地图4096 bytes.这是因为我在这里的问题中提到了窗口上较小的段错误.

#ifdef WIN32
    HANDLE fm;
    HANDLE h = (HANDLE) _get_osfhandle (fd);

    fm = CreateFileMapping(
             h,
             NULL,
             PAGE_READWRITE|SEC_RESERVE,
             0,
             16384,
             NULL);
    if (fm == NULL) { 
            fprintf (stderr, "%s: Couldn't access memory space! %s\n", argv[0],  strerror (GetLastError()));
            exit(GetLastError());
    }
    bp = (char*)MapViewOfFile(
              fm,
              FILE_MAP_ALL_ACCESS,
              0,
              0,
              0);
    if (bp == NULL) { 
            fprintf (stderr, "%s: Couldn't fill memory space! %s\n", argv[0],  strerror (GetLastError()));
            exit(GetLastError());
    }
#else
    bp = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
    if (bp == MAP_FAILED) {
            fprintf (stderr, "%s: Couldn't access memory space! %s\n", argv[0], FileName, strerror (errno));
            exit(errno);
    }
#endif
Run Code Online (Sandbox Code Playgroud)

现在发生了大量工作,将数据发送到yyout流中.最终该flushData()方法被调用.它使用空终止字符最终确定流,刷新它,然后将其倒回.然后指向内存空间的指针通过一个函数指针,以及要打印到的正确流.

void flushData(void) {
    /* write out data in the stream and reset */ 
    while (currFields < headerFields) { fprintf(yyout, ",\"\""); currFields++; } 
    currFields = 0;
    fprintf(yyout, "%c%c%c", 13, 10, '\0');
    fflush(yyout);
    rewind(yyout);
    if (faqLine == 1) {
        faqLine = 0; /* don't print faq's to the data file */
    }
    else {
        (*printString)(outfile, bp);
        fflush(outfile);
    }
    fflush(yyout);
    rewind(yyout);
}
Run Code Online (Sandbox Code Playgroud)

这是可以指向打印的功能之一.它遍历内存空间并打印每个char,直到它达到之前打印的null.

int printAnsi( FILE *outstream, char *string) {
    /* loop over the chars in string and print them to the outputstream as ansi */
    char * ps = string;
    while (*ps != '\0') {
        fprintf(outstream, "%c", *ps);
        ps++;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所有这一切的最终结果是我有一个流到内存空间就像open_memstream(),直到还有一个char指针我可以用来在必要时遍历内存空间.它是跨平台的,并且(看似)功能齐全.

如果有人想了解更多细节或记录我应该修复的问题,请添加评论.