当函数需要传递 FILE * 时,避免使用临时文件

发布于 2024-12-08 11:20:34 字数 462 浏览 7 评论 0 原文

我目前使用 C++ 使用 boost::graph 进行一些与图相关的计算。 boost::graph 可以将其图形输出为点文件,我使用 std::stringstream 来捕获输出点文件。因此,点文件的内容驻留在内存中。

我想使用点文件来可视化图形(尽可能快)。因此我想生成点文件,生成 svg 文件并将其打印到画布上。我想避免为此使用临时文件,因为图形应该很小并且内存无论如何都是可用的。

然而,graphviz libgraph 只有函数 extern Agraph_t *agread(FILE *); 我能想象到使其工作的唯一方法是在文件句柄 struct __FILE 中进行修改实在是不便携。

在 Unix/linux 中,如何让库将内存内容作为文件读取?

我刚刚发现 GraphViz 的 libcgraph 允许在此处输入重载版本,但到目前为止,文档并未指出一些有用的地方。

I currently use C++ to do some graph related computation using boost::graph.
boost::graph can output its graph as a dot file and I use a std::stringstream to capture the output dot file. Thus the contents of the dot file resides in memory.

I want to use the dot file to visualize the graph (as fast as possible). Thus I want to generate the dot file, generate an svg file and print it onto some canvas. I want to avoid using temporary files for this, as the graphs shall be small and memory is available anyway.

However graphviz libgraph has only the function extern Agraph_t *agread(FILE *); the only way I can imagine to make this working is to hack around in the filehandle struct __FILE which is really not portable.

How would you let a library read you memory contents as a file in Unix/linux?

I just found out that libcgraph from GraphViz allows to enter a overloaded version here, but so far the documentation doesn't point me to some usefull place.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

绳情 2024-12-15 11:20:34

好吧,这可以说是 API 中的一个错误,但这里有一个想法。这是假设 agread() 函数将以二进制数据的形式读取文件。

请注意,我不熟悉您正在使用的 API,但我希望这无论如何都会有用。

  1. 使用 mmap() 将文件映射到内存中。
  2. 使用该内存区域来构建图形。
  3. 当需要调用 agread() 时,将该文件描述符打开到 FILE * 结构中(fopen()fdopen( ) 如果您没有关闭描述符)。
  4. 传递 FILE * 结构。

编辑:或者,忽略我的回答并使用 fmemopen() 调用。它可能正是您所需要的。不过,我不想删除我的答案,以防有人正在写回复:-)。

Well, it is arguably a bug in the API, but here's an idea. This is assuming that the agread() function would read the file in as binary data.

Note that I am not familiar with the API you're using, but I hope this may be useful anyway.

  1. Map a file into memory using mmap().
  2. Use that memory region to do your graph construction.
  3. When it comes time to call agread(), open that file descriptor into a FILE * struct (fopen() or fdopen() if you didn't close the descriptor).
  4. Pass the FILE * struct.

Edit: Or, ignore my answer and use the fmemopen() call. It probably is exactly what you need. I didn't want to delete my answer though, in case someone is currently writing a response :-).

烟酒忠诚 2024-12-15 11:20:34

您可以使用 < 创建管道code>pipe(),将数据写入输入端,使用fdopen() 将输出文件描述符转换为适合传递给 agread() 的文件句柄。

但是,只有当您确定数据小于 PIPE_BUF 字节;否则写入可能会永远阻塞,因为另一端没有任何读取内容。

一般来说,使用临时文件更容易、更可靠。只需使用 tmpfile() 获取文件句柄,将数据写入其中,倒带并将其传递给 agread():(

fh = tmpfile();
fputs( data, fh );
rewind( fh );
graph = agread( fh );
fclose( fh );

当然,您应该检查是否有错误,但我没有这样做为了简洁起见。)

You could create a pipe with pipe(), write the data into the input end and use fdopen() to turn the output file descriptor into a filehandle suitable for passing into agread().

However, this will only work if you're sure that the data is less than PIPE_BUF bytes; otherwise the write might block forever, since there's nothing reading from the other end.

In general, using temporary files is much easier and more reliable. Just use tmpfile() to get a file handle, write the data into it, rewind and pass it to agread():

fh = tmpfile();
fputs( data, fh );
rewind( fh );
graph = agread( fh );
fclose( fh );

(Of course, you should check for errors, which I didn't for the sake of brevity.)

滴情不沾 2024-12-15 11:20:34

如果您愿意使用 GNU libc 扩展,您可以将 C 字符串作为 FILE* 打开;该文档位于 http://www.gnu.org/s /libc/manual/html_node/String-Streams.html

If you are willing to use a GNU libc extension, you can open a C string as a FILE*; the documentation is at http://www.gnu.org/s/libc/manual/html_node/String-Streams.html.

若能看破又如何 2024-12-15 11:20:34

在 Windows 上,您可以使用 fopen 打开命名管道。

FILE* f = fopen("\\\\.\\Pipe\\<pipe name>", "rb");

因此,您可以在单独的线程中创建一个管道,在其中推送数据,agread 将从其中读取数据,而不需要临时文件。

On Windows, you can open a named pipe with fopen.

FILE* f = fopen("\\\\.\\Pipe\\<pipe name>", "rb");

So you can create a pipe in a separate thread where you push the data on it, and agread will read from it without a need for a temporary file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文