开发者

Avoiding the use of temporary files, when the function wants a FILE * passed

I currently use C++ to do some gra开发者_开发百科ph 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.


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 :-).


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.)


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜