有限状态机与行为树的C++学习与实践sudo apt-get install libxmu-dev sudo apt-get install libxmu-dev libxi-dev

git clone



GraphViz and C++

C/C++ Users Journal December, 2005

Drawing directed and undirected graphs

By Nikos Platis and Mihalis Tsoukalos

Nikos Platis holds a Ph.D. in computer science from the University of Athens, Greece. His research interests are in multiresolution methods for computer graphics. He can be reached at Mihalis Tsoukalos holds a B.S. in mathematics from the University of Patras in Greece and an M.S. in IT from the University College, London. His research interests are in DBMS. He can be reached at

GraphViz is a software package for drawing directed and undirected graphs [1]. Developed by AT&T [2], GraphViz is mainly written in C, although newer parts are written in C++ and Java. Bindings for GraphViz exist in many high-level languages. For C++, mfgraph [6] is a simple binding to dot, the GraphViz language, although it appears unmaintained. A more recent binding is contained in the Boost Graph Library (BGL) [7]. The BGL offers a generic interface for representing and manipulating graphs, so its connection to GraphViz is natural. In this article, we present examples of using the BGL to create GraphViz graphs. Although there are graphical tools based on GraphViz that can graphically create graphs, in this article we focus on command-line tools in combination with C++. We use GraphViz 2.0, g++ 3.4.1, and Boost 1.32.0.

There are three major programs for creating graphs, all of which use the dot language:

  • dot is a utility program for drawing directed graphs [5].
  • NEATO is a utility program for drawing undirected graphs. This kind of graph is commonly used in telecommunications and computer programming. NEATO uses an implementation of the Kamada-Kawai algorithm for "symmetric" layouts [4].
  • twopi can draw graphs using a circular layout. One of the nodes is chosen as the center, and the other nodes are placed around the center node in a circular way. If a node is connected to the center node, it is placed at distance 1; if a node is connected to a node that is directly connected to the center node, it is placed at distance 2, and so on.

A graph contains nodes and edges, each of them having attributes. Table 1 shows some of the available attributes for dot nodes, while Table 2 shows part of the available edge attributes. There are also attributes for the graph that are not mentioned here. Similar attributes exist for the NEATO program.

Before getting the output of a GraphViz source file, the source file should be compiled. The general form of execution is:

toolname -Tps -o
where toolname denotes the name of the tool to execute (dot, NEATO, or twopi); -Tps denotes that the output file is in PostScript (other supported output formats are GIF, PNG, JPEG, HP-GL/2 vector format, VRML, and FrameMaker MIF); shows the name of the file to be processed; and -o tells what the output filename should be.

To illustrate how you can use the GraphViz language, we start with the familiar "Hello world!" example. This code produces the output in Figure 1:

digraph G
   "Hello world!";

while this command produces the PostScript file for Figure 1:

dot -Tps -o

The word digraph means that a directed graph is going to be created. For creating an undirected graph, use the word graph instead.

Listing 1 is dot code to draw the hash table in Figure 2. The command rankdir = LR denotes that the graph nodes are going to be drawn from left to right. The command node [shape=record, width=.1, height=.1] defines some node attributes. The {} characters inside the label parameter of the nodes tell the dot language to arrange the record parts left to right instead of one above another. Commands of the type nd0:p2 -> nd6:e create the connections between the nodes (the edges of the graph). The command that produces Figure 2 is:

dot -Tps -o

Integrating GraphViz and C++

The BGL contains an interface to the dot language. The function read_graphviz(fname, g) can be used to construct a BGL graph g from its representation in the .dot file with the given filename, and the function write_graphviz(fname, g) writes a BGL graph g in dot language in the given file. The graph g that can be used in these functions must be of the specific type boost::GraphvizGraph or boost::GraphvizDigraph, for undirected and directed graphs, respectively. These types carry node and edge attributes in a form suitable for expression in the dot language, namely as pairs of std::string(s), where the first string is the dot attribute name (for instance, shape) and the second one is the attribute value (box, for example). These attributes are accessed through attribute maps (they really are multimaps, in STL terms), which map a vertex to its attributes.

Suppose you want to draw a graph representing the directory structure of a filesystem. In this graph, the nodes will be the directories of the filesystem, and the (directed) edges will connect each directory to its subdirectories. The traversal of the directory hierarchy can be performed in a simple and portable way with the help of the Boost Filesystem Library. Listing 2 is our program.

The hierarchy traversal starts at a given path. For each subdirectory encountered, a node is added to the graph labeled with its name, and an edge connects it with its parent directory. The process continues recursively, until either no more subdirectories exist or a maximum recursion depth is reached.

The resulting file must be processed with dot to produce the graphical representation of the directory tree. Unfortunately, for deep and involved hierarchies, the graph produced can be very complex. Figure 3 presents a sample directory structure visualized as a graph.

Another example is a sparse matrix, which is a matrix in which most values are equal to zero. To reduce storage costs, such matrices are represented by storing only the values and coordinates of their non-zero elements. One interface to sparse matrices is provided by uBLAS, the Boost Basic Linear Algebra Library. uBLAS provides different storage models for the sparse matrices, each of them suitable for different access patterns. Typical of C++, their interface is identical, and for this example we use the class sparse_matrix. Iteration through the matrix elements is provided by two iterator classes for the rows and columns of the matrix, respectively.

Listing 3 presents functions for the row-major and column-major traversal of the tables. Let us describe the first one briefly, which creates a row-major graph representation of a sparse matrix. A node is created for each row (a "row head"), labeled with its number. Then, for each element of that row, a node is created, labeled with the column number of the element and its value; these nodes are shaped as dot "records" so that they can be subdivided into two fields, just like the nodes of the aforementioned hash table. Figure 4 is a graph representation of a sparse matrix; Figure 5 is the graph representation of the same sparse matrix.


GraphViz is a useful set of tools for drawing both directed and undirected graphs. It offers great flexibility either alone or combined with C++ with the help of the Boost Graph Library. In this article, we presented examples that demonstrate how various data structures can be represented as graphs in the BGL and visualized with GraphViz. More advanced uses of the Boost GraphViz C++ interface are possible, which will require more complex handling of the graph structure.


  1. GraphViz development web site:
  2. Official GraphViz web site: graphviz/.
  3. Junger, Michael and Petra Mutzel (editors). Graph Drawing Software, Mathematics + Visualization, Springer, ISBN 3540008810.
  4. Kamada, T. and S. Kawai. "An Algorithm for Drawing General Undirected Graphs," Information Processing Letters, April 1989.
  5. Gansner, Emden R., Eleftherios Koutsofios, Stephen C. North, and Kiem-Phong Vo. "A Technique for Drawing Directed Graphs," IEEE Trans. Software Engineering, May 1993.
  7. Boost Library web site:


#include <stdio.h>

#include <graphviz/gvc.h>
# include <graphviz/cgraph.h>
# include <graphviz/graph.h>

int main(int argc, char **argv)
    GVC_t *gvc;
    Agraph_t *g;
    Agnode_t *t, *h;

    g = agopen("test", Agdirected, NULL);
    printf("agopen %p\n", g);
    t = agnode(g, "a", 1);
    h = agnode(g, "b", 1);
    agedge(g, t, h, "x", 1);
    g = agopen("test", AGDIGRAPH);
    printf("agopen %p\n", g);
    t = agnode(g, "a");
    h = agnode(g, "b");
    agedge(g, t, h);

    FILE *f = fopen("", "w");
    agwrite(g, f);

    gvc = gvContext();
    printf("gvContext %p\n", gvc);
    gvLayout(gvc, g, "dot");

    return 0;


$ pkg-config libcgraph --cflags --libs
-I/usr/include/graphviz  -lcgraph -lcdt  
$ pkg-config libgvc --cflags --libs 
-I/usr/include/graphviz  -lgvc -lgraph -lcdt
$ gcc foo.c -o foo -DWITH_CGRAPH `pkg-config libcgraph libgvc --cflags --libs`
$ ./foo
agopen 0x956d050
Segmentation fault (core dumped)

I've been trying to resolve this for hours now and couldn't find anything useful. All posts and tutorials I can find are all using libcgraph or libgraph only and not also libgvc.

libgvc requires libgraph but even if I rewrite the program to use libgraph it crashes (although then it crahes at gvLayout).
Does anybody know how this stuff works? I've only done my first graphviz stuff today so I'm not too familiar with all this.

$ uname -a
Linux mybox 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:32:50 UTC 2012 i686 i686 i386 GNU/Linux
$ dpkg -l | grep -E "libgraph|libcgraph|libgvc|libcdt"
ii  libcdt4                                2.26.3-10ubuntu1                           rich set of graph drawing tools - cdt library
ii  libcgraph5                             2.26.3-10ubuntu1                           rich set of graph drawing tools - cgraph library
ii  libgraph4                              2.26.3-10ubuntu1                           rich set of graph drawing tools - graph library
ii  libgraphicsmagick3                     1.3.12-1.1build1                           format-independent image processing - C shared library
ii  libgraphviz-dev                        2.26.3-10ubuntu1                           graphviz libs and headers against which to build applications
ii  libgvc5                                2.26.3-10ubuntu1                           rich set of graph drawing tools - gvc library

csnafu is offlineFirst Cup of Ubuntu
Join Date
Jun 2012

Re: Graphviz using gvc and cgraph in one program

Could at least someone compile this and tell me if it segfaults for him as well?

glennric is offlineIced Almond Soy Ubuntu, No Foam
Join Date
Feb 2006
Ubuntu 13.10 Saucy Salamander

Re: Graphviz using gvc and cgraph in one program

I compiled it. It segmentation faults for me to. A backtrace shows that it is from your agopen call. I haven't looked any deeper than that though.


  • 发表于 9个月前
  • 阅读 60
  • 收藏 1
  • 点赞 0
  • 评论0






sudo apt-get install graphviz-dev


dot -version



digraph G {
    a[label="node a",shape=record];
    b[label="node b",shape=ellipse];
    a->b[label="edge a-> b"];



dot myfirst.gv -T png -o myfirst.png






digraph/graph graph_name {


            在本例中,此图是一个有向图,名字为G,有三个元素:节点a,标题为“node a”,形状是矩形;节点b,标题为“node b”,形状是椭圆(默认);有向连线a->b,标题为“edge a -> b ”。


neato myfirst.gv -T png -o myfirst.png




            跟GCC一样,命令的第二个参数是输入文件,-o 后面是输出文件,-T后面是输出文件的格式,可以是各种图形格式例如:PNG、JPG、GIF、SVG、PDF、PS甚至是非图形的DOT语言自己,在这里你可能会说,DOT格式不是变回自己吗,这也有意义?答案是,有,但不是这里。再以后的章节我会详细说明。  



#include <stdio>
#include <gvc.h>

int main(){
    GVC_t * gv;
    Agraph_t * g;
    Agnode_t * a,* b;
    Agedge_t * e;

    a=agnode(g,"node a",1);
    b=agnode(g,"node b",1);
    e=agedge(g,a,b,"edge e",1);
    agsafeset(e,"label","edge a -> b","");

            同目录终端输入以下命令,编译运行,编译时有可能会有很多警告,这是由于gvc接口的字符串参数类型为char *,而源代码中字符串类型为const char *,可以忽略:

g++ myfirst.cpp -o myfirst `pkg-config --libs --cflags libgvc`



digraph G {
	graph [bb="0,0,97.447,123"];
	node [label="\N",
	"node a"	 [height=0.5,
	"node b"	 [height=0.5,
	"node a" -> "node b" [key="edge e",
	label="edge a -> b",
	pos="e,34.447,36.175 34.447,86.799 34.447,75.163 34.447,59.548 34.447,46.237"];




pkg-config --libs --cflags libgvc



            使用之前,必需导入程式库的句柄——gv,是一个GVC_t 类型的指针,包含对图进行布局和渲染输出的必要函数,通过gvContext()获取,使用完毕后通过gvFreeContext()释放。




glennric is offlineIced Almond Soy Ubuntu, No Foam
Join Date
Feb 2006
Ubuntu 13.10 Saucy Salamander

Re: Graphviz using gvc and cgraph in one program

I compiled it. It segmentation faults for me to. A backtrace shows that it is from your agopen call. I haven't looked any deeper than that though.

glennric is offlineIced Almond Soy Ubuntu, No Foam
Join Date
Feb 2006
Ubuntu 13.10 Saucy Salamander

Re: Graphviz using gvc and cgraph in one program

Actually, I didn't look close enough. I get the same crash points as you do.

个人分类: LinuxOmapL138 BondGraph
想对作者说点什么? 我来说一句



有限状态机与行为树的C++学习与实践sudo apt-get install libxmu-dev sudo apt-get install libxmu-dev libxi-dev