对于那些追随我的人,有希望!有一个解决方案。正如我的问题所述,我使用的是open_memstream(),它在 Windows 上不受支持。
由于我有一个File * 指针(不能更改为char *),我需要将它重定向到内存,直到稍后。由于我正在处理内存中的文件,因此我查看了mmap()。它可以轻松解决问题,但同样,它只是 linux。
但是,Windows 包含一个对 mmap() 的推论,称为 MapViewOfFile()。通过#ifdef 的魔力,我可以根据需要使用它:
#ifdef WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
稍后,在 main 方法中,我调用了两个平台都支持的 tmpfile()。这将为我打开一个流到一个有保证的唯一临时文件的流。现在我有了FILE * 指针,我需要mmap() 空间。但是mmap()需要的是文件描述符,而不是流,所以我使用fileno()函数来获取新的文件描述符。
/* create tmp file and get file descriptor */
int fd;
yyout = tmpfile();
fd = fileno(yyout);
现在我有更多#ifdef 代码来确定需要使用哪个内存映射代码集。请注意两个版本之间映射空间的差异。 Windows 映射 16384 bytes 和 linux 映射 4096 bytes。这是因为较小的值会在 Windows 上出现段错误,如 my question here 中所述。
#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
现在发生了一堆工作,将数据发送到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);
}
这是可以指向打印的函数之一。它遍历内存空间并打印每个字符,直到遇到之前打印的 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;
}
所有这一切的最终结果是我有一个流到内存空间的流,就像open_memstream() 一样,还有一个 char 指针,我可以在必要时使用它来遍历内存空间。它是跨平台的,并且(看似)功能齐全。
如果有人想了解更多详细信息或对我应该解决的问题有注释,请添加评论。