root / docs / qapi-code-gen.txt @ 69dd62df
History | View | Annotate | Download (14.3 kB)
1 |
= How to use the QAPI code generator = |
---|---|
2 |
|
3 |
* Note: as of this writing, QMP does not use QAPI. Eventually QMP |
4 |
commands will be converted to use QAPI internally. The following |
5 |
information describes QMP/QAPI as it will exist after the |
6 |
conversion. |
7 |
|
8 |
QAPI is a native C API within QEMU which provides management-level |
9 |
functionality to internal/external users. For external |
10 |
users/processes, this interface is made available by a JSON-based |
11 |
QEMU Monitor protocol that is provided by the QMP server. |
12 |
|
13 |
To map QMP-defined interfaces to the native C QAPI implementations, |
14 |
a JSON-based schema is used to define types and function |
15 |
signatures, and a set of scripts is used to generate types/signatures, |
16 |
and marshaling/dispatch code. The QEMU Guest Agent also uses these |
17 |
scripts, paired with a separate schema, to generate |
18 |
marshaling/dispatch code for the guest agent server running in the |
19 |
guest. |
20 |
|
21 |
This document will describe how the schemas, scripts, and resulting |
22 |
code is used. |
23 |
|
24 |
|
25 |
== QMP/Guest agent schema == |
26 |
|
27 |
This file defines the types, commands, and events used by QMP. It should |
28 |
fully describe the interface used by QMP. |
29 |
|
30 |
This file is designed to be loosely based on JSON although it's technically |
31 |
executable Python. While dictionaries are used, they are parsed as |
32 |
OrderedDicts so that ordering is preserved. |
33 |
|
34 |
There are two basic syntaxes used, type definitions and command definitions. |
35 |
|
36 |
The first syntax defines a type and is represented by a dictionary. There are |
37 |
three kinds of user-defined types that are supported: complex types, |
38 |
enumeration types and union types. |
39 |
|
40 |
Generally speaking, types definitions should always use CamelCase for the type |
41 |
names. Command names should be all lower case with words separated by a hyphen. |
42 |
|
43 |
=== Complex types === |
44 |
|
45 |
A complex type is a dictionary containing a single key whose value is a |
46 |
dictionary. This corresponds to a struct in C or an Object in JSON. An |
47 |
example of a complex type is: |
48 |
|
49 |
{ 'type': 'MyType', |
50 |
'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } } |
51 |
|
52 |
The use of '*' as a prefix to the name means the member is optional. Optional |
53 |
members should always be added to the end of the dictionary to preserve |
54 |
backwards compatibility. |
55 |
|
56 |
=== Enumeration types === |
57 |
|
58 |
An enumeration type is a dictionary containing a single key whose value is a |
59 |
list of strings. An example enumeration is: |
60 |
|
61 |
{ 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } |
62 |
|
63 |
=== Union types === |
64 |
|
65 |
Union types are used to let the user choose between several different data |
66 |
types. A union type is defined using a dictionary as explained in the |
67 |
following paragraphs. |
68 |
|
69 |
|
70 |
A simple union type defines a mapping from discriminator values to data types |
71 |
like in this example: |
72 |
|
73 |
{ 'type': 'FileOptions', 'data': { 'filename': 'str' } } |
74 |
{ 'type': 'Qcow2Options', |
75 |
'data': { 'backing-file': 'str', 'lazy-refcounts': 'bool' } } |
76 |
|
77 |
{ 'union': 'BlockdevOptions', |
78 |
'data': { 'file': 'FileOptions', |
79 |
'qcow2': 'Qcow2Options' } } |
80 |
|
81 |
In the QMP wire format, a simple union is represented by a dictionary that |
82 |
contains the 'type' field as a discriminator, and a 'data' field that is of the |
83 |
specified data type corresponding to the discriminator value: |
84 |
|
85 |
{ "type": "qcow2", "data" : { "backing-file": "/some/place/my-image", |
86 |
"lazy-refcounts": true } } |
87 |
|
88 |
|
89 |
A union definition can specify a complex type as its base. In this case, the |
90 |
fields of the complex type are included as top-level fields of the union |
91 |
dictionary in the QMP wire format. An example definition is: |
92 |
|
93 |
{ 'type': 'BlockdevCommonOptions', 'data': { 'readonly': 'bool' } } |
94 |
{ 'union': 'BlockdevOptions', |
95 |
'base': 'BlockdevCommonOptions', |
96 |
'data': { 'raw': 'RawOptions', |
97 |
'qcow2': 'Qcow2Options' } } |
98 |
|
99 |
And it looks like this on the wire: |
100 |
|
101 |
{ "type": "qcow2", |
102 |
"readonly": false, |
103 |
"data" : { "backing-file": "/some/place/my-image", |
104 |
"lazy-refcounts": true } } |
105 |
|
106 |
|
107 |
Flat union types avoid the nesting on the wire. They are used whenever a |
108 |
specific field of the base type is declared as the discriminator ('type' is |
109 |
then no longer generated). The discriminator must always be a string field. |
110 |
The above example can then be modified as follows: |
111 |
|
112 |
{ 'type': 'BlockdevCommonOptions', |
113 |
'data': { 'driver': 'str', 'readonly': 'bool' } } |
114 |
{ 'union': 'BlockdevOptions', |
115 |
'base': 'BlockdevCommonOptions', |
116 |
'discriminator': 'driver', |
117 |
'data': { 'raw': 'RawOptions', |
118 |
'qcow2': 'Qcow2Options' } } |
119 |
|
120 |
Resulting in this JSON object: |
121 |
|
122 |
{ "driver": "qcow2", |
123 |
"readonly": false, |
124 |
"backing-file": "/some/place/my-image", |
125 |
"lazy-refcounts": true } |
126 |
|
127 |
|
128 |
A special type of unions are anonymous unions. They don't form a dictionary in |
129 |
the wire format but allow the direct use of different types in their place. As |
130 |
they aren't structured, they don't have any explicit discriminator but use |
131 |
the (QObject) data type of their value as an implicit discriminator. This means |
132 |
that they are restricted to using only one discriminator value per QObject |
133 |
type. For example, you cannot have two different complex types in an anonymous |
134 |
union, or two different integer types. |
135 |
|
136 |
Anonymous unions are declared using an empty dictionary as their discriminator. |
137 |
The discriminator values never appear on the wire, they are only used in the |
138 |
generated C code. Anonymous unions cannot have a base type. |
139 |
|
140 |
{ 'union': 'BlockRef', |
141 |
'discriminator': {}, |
142 |
'data': { 'definition': 'BlockdevOptions', |
143 |
'reference': 'str' } } |
144 |
|
145 |
This example allows using both of the following example objects: |
146 |
|
147 |
{ "file": "my_existing_block_device_id" } |
148 |
{ "file": { "driver": "file", |
149 |
"readonly": false, |
150 |
'filename': "/tmp/mydisk.qcow2" } } |
151 |
|
152 |
|
153 |
=== Commands === |
154 |
|
155 |
Commands are defined by using a list containing three members. The first |
156 |
member is the command name, the second member is a dictionary containing |
157 |
arguments, and the third member is the return type. |
158 |
|
159 |
An example command is: |
160 |
|
161 |
{ 'command': 'my-command', |
162 |
'data': { 'arg1': 'str', '*arg2': 'str' }, |
163 |
'returns': 'str' } |
164 |
|
165 |
|
166 |
== Code generation == |
167 |
|
168 |
Schemas are fed into 3 scripts to generate all the code/files that, paired |
169 |
with the core QAPI libraries, comprise everything required to take JSON |
170 |
commands read in by a QMP/guest agent server, unmarshal the arguments into |
171 |
the underlying C types, call into the corresponding C function, and map the |
172 |
response back to a QMP/guest agent response to be returned to the user. |
173 |
|
174 |
As an example, we'll use the following schema, which describes a single |
175 |
complex user-defined type (which will produce a C struct, along with a list |
176 |
node structure that can be used to chain together a list of such types in |
177 |
case we want to accept/return a list of this type with a command), and a |
178 |
command which takes that type as a parameter and returns the same type: |
179 |
|
180 |
mdroth@illuin:~/w/qemu2.git$ cat example-schema.json |
181 |
{ 'type': 'UserDefOne', |
182 |
'data': { 'integer': 'int', 'string': 'str' } } |
183 |
|
184 |
{ 'command': 'my-command', |
185 |
'data': {'arg1': 'UserDefOne'}, |
186 |
'returns': 'UserDefOne' } |
187 |
mdroth@illuin:~/w/qemu2.git$ |
188 |
|
189 |
=== scripts/qapi-types.py === |
190 |
|
191 |
Used to generate the C types defined by a schema. The following files are |
192 |
created: |
193 |
|
194 |
$(prefix)qapi-types.h - C types corresponding to types defined in |
195 |
the schema you pass in |
196 |
$(prefix)qapi-types.c - Cleanup functions for the above C types |
197 |
|
198 |
The $(prefix) is an optional parameter used as a namespace to keep the |
199 |
generated code from one schema/code-generation separated from others so code |
200 |
can be generated/used from multiple schemas without clobbering previously |
201 |
created code. |
202 |
|
203 |
Example: |
204 |
|
205 |
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \ |
206 |
--output-dir="qapi-generated" --prefix="example-" < example-schema.json |
207 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c |
208 |
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
209 |
|
210 |
#include "qapi/qapi-dealloc-visitor.h" |
211 |
#include "example-qapi-types.h" |
212 |
#include "example-qapi-visit.h" |
213 |
|
214 |
void qapi_free_UserDefOne(UserDefOne * obj) |
215 |
{ |
216 |
QapiDeallocVisitor *md; |
217 |
Visitor *v; |
218 |
|
219 |
if (!obj) { |
220 |
return; |
221 |
} |
222 |
|
223 |
md = qapi_dealloc_visitor_new(); |
224 |
v = qapi_dealloc_get_visitor(md); |
225 |
visit_type_UserDefOne(v, &obj, NULL, NULL); |
226 |
qapi_dealloc_visitor_cleanup(md); |
227 |
} |
228 |
|
229 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h |
230 |
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
231 |
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES |
232 |
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES |
233 |
|
234 |
#include "qapi/qapi-types-core.h" |
235 |
|
236 |
typedef struct UserDefOne UserDefOne; |
237 |
|
238 |
typedef struct UserDefOneList |
239 |
{ |
240 |
UserDefOne *value; |
241 |
struct UserDefOneList *next; |
242 |
} UserDefOneList; |
243 |
|
244 |
struct UserDefOne |
245 |
{ |
246 |
int64_t integer; |
247 |
char * string; |
248 |
}; |
249 |
|
250 |
void qapi_free_UserDefOne(UserDefOne * obj); |
251 |
|
252 |
#endif |
253 |
|
254 |
|
255 |
=== scripts/qapi-visit.py === |
256 |
|
257 |
Used to generate the visitor functions used to walk through and convert |
258 |
a QObject (as provided by QMP) to a native C data structure and |
259 |
vice-versa, as well as the visitor function used to dealloc a complex |
260 |
schema-defined C type. |
261 |
|
262 |
The following files are generated: |
263 |
|
264 |
$(prefix)qapi-visit.c: visitor function for a particular C type, used |
265 |
to automagically convert QObjects into the |
266 |
corresponding C type and vice-versa, as well |
267 |
as for deallocating memory for an existing C |
268 |
type |
269 |
|
270 |
$(prefix)qapi-visit.h: declarations for previously mentioned visitor |
271 |
functions |
272 |
|
273 |
Example: |
274 |
|
275 |
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \ |
276 |
--output-dir="qapi-generated" --prefix="example-" < example-schema.json |
277 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c |
278 |
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
279 |
|
280 |
#include "example-qapi-visit.h" |
281 |
|
282 |
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp) |
283 |
{ |
284 |
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp); |
285 |
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp); |
286 |
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp); |
287 |
visit_end_struct(m, errp); |
288 |
} |
289 |
|
290 |
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp) |
291 |
{ |
292 |
GenericList *i, **prev = (GenericList **)obj; |
293 |
|
294 |
visit_start_list(m, name, errp); |
295 |
|
296 |
for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) { |
297 |
UserDefOneList *native_i = (UserDefOneList *)i; |
298 |
visit_type_UserDefOne(m, &native_i->value, NULL, errp); |
299 |
} |
300 |
|
301 |
visit_end_list(m, errp); |
302 |
} |
303 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h |
304 |
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
305 |
|
306 |
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT |
307 |
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT |
308 |
|
309 |
#include "qapi/qapi-visit-core.h" |
310 |
#include "example-qapi-types.h" |
311 |
|
312 |
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp); |
313 |
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp); |
314 |
|
315 |
#endif |
316 |
mdroth@illuin:~/w/qemu2.git$ |
317 |
|
318 |
(The actual structure of the visit_type_* functions is a bit more complex |
319 |
in order to propagate errors correctly and avoid leaking memory). |
320 |
|
321 |
=== scripts/qapi-commands.py === |
322 |
|
323 |
Used to generate the marshaling/dispatch functions for the commands defined |
324 |
in the schema. The following files are generated: |
325 |
|
326 |
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each |
327 |
QMP command defined in the schema. Functions |
328 |
generated by qapi-visit.py are used to |
329 |
convert QObjects received from the wire into |
330 |
function parameters, and uses the same |
331 |
visitor functions to convert native C return |
332 |
values to QObjects from transmission back |
333 |
over the wire. |
334 |
|
335 |
$(prefix)qmp-commands.h: Function prototypes for the QMP commands |
336 |
specified in the schema. |
337 |
|
338 |
Example: |
339 |
|
340 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c |
341 |
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
342 |
|
343 |
#include "qemu-objects.h" |
344 |
#include "qapi/qmp-core.h" |
345 |
#include "qapi/qapi-visit-core.h" |
346 |
#include "qapi/qmp-output-visitor.h" |
347 |
#include "qapi/qmp-input-visitor.h" |
348 |
#include "qapi/qapi-dealloc-visitor.h" |
349 |
#include "example-qapi-types.h" |
350 |
#include "example-qapi-visit.h" |
351 |
|
352 |
#include "example-qmp-commands.h" |
353 |
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp) |
354 |
{ |
355 |
QapiDeallocVisitor *md = qapi_dealloc_visitor_new(); |
356 |
QmpOutputVisitor *mo = qmp_output_visitor_new(); |
357 |
Visitor *v; |
358 |
|
359 |
v = qmp_output_get_visitor(mo); |
360 |
visit_type_UserDefOne(v, &ret_in, "unused", errp); |
361 |
v = qapi_dealloc_get_visitor(md); |
362 |
visit_type_UserDefOne(v, &ret_in, "unused", errp); |
363 |
qapi_dealloc_visitor_cleanup(md); |
364 |
|
365 |
|
366 |
*ret_out = qmp_output_get_qobject(mo); |
367 |
} |
368 |
|
369 |
static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp) |
370 |
{ |
371 |
UserDefOne * retval = NULL; |
372 |
QmpInputVisitor *mi; |
373 |
QapiDeallocVisitor *md; |
374 |
Visitor *v; |
375 |
UserDefOne * arg1 = NULL; |
376 |
|
377 |
mi = qmp_input_visitor_new(QOBJECT(args)); |
378 |
v = qmp_input_get_visitor(mi); |
379 |
visit_type_UserDefOne(v, &arg1, "arg1", errp); |
380 |
|
381 |
if (error_is_set(errp)) { |
382 |
goto out; |
383 |
} |
384 |
retval = qmp_my_command(arg1, errp); |
385 |
qmp_marshal_output_my_command(retval, ret, errp); |
386 |
|
387 |
out: |
388 |
md = qapi_dealloc_visitor_new(); |
389 |
v = qapi_dealloc_get_visitor(md); |
390 |
visit_type_UserDefOne(v, &arg1, "arg1", errp); |
391 |
qapi_dealloc_visitor_cleanup(md); |
392 |
return; |
393 |
} |
394 |
|
395 |
static void qmp_init_marshal(void) |
396 |
{ |
397 |
qmp_register_command("my-command", qmp_marshal_input_my_command); |
398 |
} |
399 |
|
400 |
qapi_init(qmp_init_marshal); |
401 |
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h |
402 |
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ |
403 |
|
404 |
#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS |
405 |
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS |
406 |
|
407 |
#include "example-qapi-types.h" |
408 |
#include "error.h" |
409 |
|
410 |
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp); |
411 |
|
412 |
#endif |
413 |
mdroth@illuin:~/w/qemu2.git$ |