本文介绍如何与C / C ++预处理器(以下简称为预处理器)配合使用流行的Graphviz绘图工具。
关键是Graphviz使用的点图语言在语法上适用于预处理器处理。因此由开发商构想。由于他们的洞察力,我们在描述图形时可以使用以下功能(我从内存中引用维基百科):
- 用等效的字符“#”和“ \”替换相应的有向图和有向图;
- 删除转义的换行符;
- 用空行替换行和块注释(删除周围的空格和制表符);
- 插入(包含)任意文件(#include)的内容;
- 宏替换(#define);
- 条件编译(#if,#ifdef,#elif,#else,#endif);
现在,我们将在实践中展示开放的机会。例如,以我在MediaStrimer2上的文章中的图表为例,如下图所示。

该图足够大,如果您在“额头上”描述它,那么将需要大量的手动无差错工作。如果仔细观察,您可以隔离仅在某些字段内容上有所不同的重复元素。这就是图的节点看起来像m 1,m2,m2_1,m2_2,m3,m4的样子。这些是使用宏的小型机械化方法的首批候选对象。为我们的主要点文件创建头文件。我们称之为common.dot:
#define Q(x) #x
#define QUOTE(x) Q(x)
#define msg_staff \
<p> *prev \
|<n> *next \
|<c> *cont \
|<d> *data \
| other\nstuff
#define msg(name, ... ) \
name[xlabel=mblk_t label=QUOTE(<h> name | msg_staff) \
];
#define dbuf(name ...) \
name[label=QUOTE(<h> name) xlabel="dblk_t"];
#define queue(name, ...) \
name[ xlabel="queue_t" label=QUOTE(<h> name | \
msg_staff)];
现在是时候编写主图形文件了。我们称之为my_graph.dot:
#include "common.dot"
digraph queue_demo
{
rankdir=LR;
node[shape=Mrecord];
dbuf(d1);
dbuf(d2);
dbuf(d2_1);
dbuf(d2_2);
dbuf(d3);
dbuf(d4);
msg(m1);
msg(m2);
msg(m2_1);
msg(m2_2);
msg(m3);
msg(m4);
queue(q1);
m1:d->d1;
m2:d->d2;
m2_1:d->d2_1;
m2_2:d->d2_2;
m3:d->d3;
m4:d->d4;
m1:n -> m2:h;
m1:p -> q1:h;
m2:n -> m3:h;
m2:c->m2_1:h;
m2_1:c->m2_2:h;
m3:n -> m4:h;
m2:p -> m1:h;
m3:p -> m2:h;
m4:p -> m3:h;
q1:n->m1:h;
q1:p->m4:h;
m4:n -> q1:h[color=blue];
}
我们使用预处理器处理文件:
cpp my_graph.dot -o my_graph_res.dot
my_graph_res.dot. :
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "my_graph.dot"
# 1 "common.dot" 1
# 3 "my_graph.dot" 2
digraph queue_demo
{
rankdir=LR;
node[shape=Mrecord];
d1[label="<h> d1" xlabel="dblk_t"];;
d2[label="<h> d2" xlabel="dblk_t"];;
d2_1[label="<h> d2_1" xlabel="dblk_t"];;
d2_2[label="<h> d2_2" xlabel="dblk_t"];;
d3[label="<h> d3" xlabel="dblk_t"];;
d4[label="<h> d4" xlabel="dblk_t"];;
m1[xlabel=mblk_t label="<h> m1 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
m2[xlabel=mblk_t label="<h> m2 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
m2_1[xlabel=mblk_t label="<h> m2_1 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
m2_2[xlabel=mblk_t label="<h> m2_2 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
m3[xlabel=mblk_t label="<h> m3 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
m4[xlabel=mblk_t label="<h> m4 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff" ];;
q1[ xlabel="queue_t" label="<h> q1 | <p> *prev |<n> *next |<c> *cont |<d> *data | other\nstuff"];;
m1:d->d1;
m2:d->d2;
m2_1:d->d2_1;
m2_2:d->d2_2;
m3:d->d3;
m4:d->d4;
m1:n -> m2:h;
m1:p -> q1:h;
m2:n -> m3:h;
m2:c->m2_1:h;
m2_1:c->m2_2:h;
m3:n -> m4:h;
m2:p -> m1:h;
m3:p -> m2:h;
m4:p -> m3:h;
q1:n->m1:h;
q1:p->m4:h;
m4:n -> q1:h[color=blue];
}
, . . Graphviz ( dot) : https://sketchviz.com/new
:

, , .
.