我目前使用 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.
发布评论
评论(4)
好吧,这可以说是 API 中的一个错误,但这里有一个想法。这是假设 agread() 函数将以二进制数据的形式读取文件。
请注意,我不熟悉您正在使用的 API,但我希望这无论如何都会有用。
mmap()
将文件映射到内存中。agread()
时,将该文件描述符打开到FILE *
结构中(fopen()
或fdopen( )
如果您没有关闭描述符)。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.
mmap()
.agread()
, open that file descriptor into aFILE *
struct (fopen()
orfdopen()
if you didn't close the descriptor).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 :-).您可以使用 < 创建管道code>pipe(),将数据写入输入端,使用
fdopen()
将输出文件描述符转换为适合传递给agread()
的文件句柄。但是,只有当您确定数据小于
PIPE_BUF
字节;否则写入可能会永远阻塞,因为另一端没有任何读取内容。一般来说,使用临时文件更容易、更可靠。只需使用
tmpfile()
获取文件句柄,将数据写入其中,倒带并将其传递给agread()
:(当然,您应该检查是否有错误,但我没有这样做为了简洁起见。)
You could create a pipe with
pipe()
, write the data into the input end and usefdopen()
to turn the output file descriptor into a filehandle suitable for passing intoagread()
.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 toagread()
:(Of course, you should check for errors, which I didn't for the sake of brevity.)
如果您愿意使用 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.在 Windows 上,您可以使用 fopen 打开命名管道。
因此,您可以在单独的线程中创建一个管道,在其中推送数据,agread 将从其中读取数据,而不需要临时文件。
On Windows, you can open a named pipe with fopen.
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.