Statistics
| Branch: | Revision:

root / docs / qapi-code-gen.txt @ d195325b

History | View | Annotate | Download (11 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
two kinds of types that are supported: complex user-defined types, and enums.
38

    
39
A complex type is a dictionary containing a single key who's value is a
40
dictionary.  This corresponds to a struct in C or an Object in JSON.  An
41
example of a complex type is:
42

    
43
 { 'type': 'MyType',
44
   'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } }
45

    
46
The use of '*' as a prefix to the name means the member is optional.  Optional
47
members should always be added to the end of the dictionary to preserve
48
backwards compatibility.
49

    
50
An enumeration type is a dictionary containing a single key who's value is a
51
list of strings.  An example enumeration is:
52

    
53
 { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
54

    
55
Generally speaking, complex types and enums should always use CamelCase for
56
the type names.
57

    
58
Commands are defined by using a list containing three members.  The first
59
member is the command name, the second member is a dictionary containing
60
arguments, and the third member is the return type.
61

    
62
An example command is:
63

    
64
 { 'command': 'my-command',
65
   'data': { 'arg1': 'str', '*arg2': 'str' },
66
   'returns': 'str' }
67

    
68
Command names should be all lower case with words separated by a hyphen.
69

    
70

    
71
== Code generation ==
72

    
73
Schemas are fed into 3 scripts to generate all the code/files that, paired
74
with the core QAPI libraries, comprise everything required to take JSON
75
commands read in by a QMP/guest agent server, unmarshal the arguments into
76
the underlying C types, call into the corresponding C function, and map the
77
response back to a QMP/guest agent response to be returned to the user.
78

    
79
As an example, we'll use the following schema, which describes a single
80
complex user-defined type (which will produce a C struct, along with a list
81
node structure that can be used to chain together a list of such types in
82
case we want to accept/return a list of this type with a command), and a
83
command which takes that type as a parameter and returns the same type:
84

    
85
    mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
86
    { 'type': 'UserDefOne',
87
      'data': { 'integer': 'int', 'string': 'str' } }
88

    
89
    { 'command': 'my-command',
90
      'data':    {'arg1': 'UserDefOne'},
91
      'returns': 'UserDefOne' }
92
    mdroth@illuin:~/w/qemu2.git$
93

    
94
=== scripts/qapi-types.py ===
95

    
96
Used to generate the C types defined by a schema. The following files are
97
created:
98

    
99
$(prefix)qapi-types.h - C types corresponding to types defined in
100
                        the schema you pass in
101
$(prefix)qapi-types.c - Cleanup functions for the above C types
102

    
103
The $(prefix) is an optional parameter used as a namespace to keep the
104
generated code from one schema/code-generation separated from others so code
105
can be generated/used from multiple schemas without clobbering previously
106
created code.
107

    
108
Example:
109

    
110
    mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
111
      --output-dir="qapi-generated" --prefix="example-" < example-schema.json
112
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
113
    /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
114

    
115
    #include "qapi/qapi-dealloc-visitor.h"
116
    #include "example-qapi-types.h"
117
    #include "example-qapi-visit.h"
118

    
119
    void qapi_free_UserDefOne(UserDefOne * obj)
120
    {
121
        QapiDeallocVisitor *md;
122
        Visitor *v;
123

    
124
        if (!obj) {
125
            return;
126
        }
127

    
128
        md = qapi_dealloc_visitor_new();
129
        v = qapi_dealloc_get_visitor(md);
130
        visit_type_UserDefOne(v, &obj, NULL, NULL);
131
        qapi_dealloc_visitor_cleanup(md);
132
    }
133

    
134
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
135
    /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
136
    #ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
137
    #define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
138

    
139
    #include "qapi/qapi-types-core.h"
140

    
141
    typedef struct UserDefOne UserDefOne;
142

    
143
    typedef struct UserDefOneList
144
    {
145
        UserDefOne *value;
146
        struct UserDefOneList *next;
147
    } UserDefOneList;
148

    
149
    struct UserDefOne
150
    {
151
        int64_t integer;
152
        char * string;
153
    };
154

    
155
    void qapi_free_UserDefOne(UserDefOne * obj);
156

    
157
    #endif
158

    
159

    
160
=== scripts/qapi-visit.py ===
161

    
162
Used to generate the visitor functions used to walk through and convert
163
a QObject (as provided by QMP) to a native C data structure and
164
vice-versa, as well as the visitor function used to dealloc a complex
165
schema-defined C type.
166

    
167
The following files are generated:
168

    
169
$(prefix)qapi-visit.c: visitor function for a particular C type, used
170
                       to automagically convert QObjects into the
171
                       corresponding C type and vice-versa, as well
172
                       as for deallocating memory for an existing C
173
                       type
174

    
175
$(prefix)qapi-visit.h: declarations for previously mentioned visitor
176
                       functions
177

    
178
Example:
179

    
180
    mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
181
        --output-dir="qapi-generated" --prefix="example-" < example-schema.json
182
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
183
    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
184

    
185
    #include "example-qapi-visit.h"
186

    
187
    void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
188
    {
189
        visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
190
        visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
191
        visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
192
        visit_end_struct(m, errp);
193
    }
194

    
195
    void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
196
    {
197
        GenericList *i, **prev = (GenericList **)obj;
198

    
199
        visit_start_list(m, name, errp);
200

    
201
        for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
202
            UserDefOneList *native_i = (UserDefOneList *)i;
203
            visit_type_UserDefOne(m, &native_i->value, NULL, errp);
204
        }
205

    
206
        visit_end_list(m, errp);
207
    }
208
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
209
    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
210

    
211
    #ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
212
    #define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
213

    
214
    #include "qapi/qapi-visit-core.h"
215
    #include "example-qapi-types.h"
216

    
217
    void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
218
    void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
219

    
220
    #endif
221
    mdroth@illuin:~/w/qemu2.git$
222

    
223
(The actual structure of the visit_type_* functions is a bit more complex
224
in order to propagate errors correctly and avoid leaking memory).
225

    
226
=== scripts/qapi-commands.py ===
227

    
228
Used to generate the marshaling/dispatch functions for the commands defined
229
in the schema. The following files are generated:
230

    
231
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
232
                        QMP command defined in the schema. Functions
233
                        generated by qapi-visit.py are used to
234
                        convert QObjects received from the wire into
235
                        function parameters, and uses the same
236
                        visitor functions to convert native C return
237
                        values to QObjects from transmission back
238
                        over the wire.
239

    
240
$(prefix)qmp-commands.h: Function prototypes for the QMP commands
241
                         specified in the schema.
242

    
243
Example:
244

    
245
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
246
    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
247

    
248
    #include "qemu-objects.h"
249
    #include "qapi/qmp-core.h"
250
    #include "qapi/qapi-visit-core.h"
251
    #include "qapi/qmp-output-visitor.h"
252
    #include "qapi/qmp-input-visitor.h"
253
    #include "qapi/qapi-dealloc-visitor.h"
254
    #include "example-qapi-types.h"
255
    #include "example-qapi-visit.h"
256

    
257
    #include "example-qmp-commands.h"
258
    static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
259
    {
260
        QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
261
        QmpOutputVisitor *mo = qmp_output_visitor_new();
262
        Visitor *v;
263

    
264
        v = qmp_output_get_visitor(mo);
265
        visit_type_UserDefOne(v, &ret_in, "unused", errp);
266
        v = qapi_dealloc_get_visitor(md);
267
        visit_type_UserDefOne(v, &ret_in, "unused", errp);
268
        qapi_dealloc_visitor_cleanup(md);
269

    
270

    
271
        *ret_out = qmp_output_get_qobject(mo);
272
    }
273

    
274
    static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
275
    {
276
        UserDefOne * retval = NULL;
277
        QmpInputVisitor *mi;
278
        QapiDeallocVisitor *md;
279
        Visitor *v;
280
        UserDefOne * arg1 = NULL;
281

    
282
        mi = qmp_input_visitor_new(QOBJECT(args));
283
        v = qmp_input_get_visitor(mi);
284
        visit_type_UserDefOne(v, &arg1, "arg1", errp);
285

    
286
        if (error_is_set(errp)) {
287
            goto out;
288
        }
289
        retval = qmp_my_command(arg1, errp);
290
        qmp_marshal_output_my_command(retval, ret, errp);
291

    
292
    out:
293
        md = qapi_dealloc_visitor_new();
294
        v = qapi_dealloc_get_visitor(md);
295
        visit_type_UserDefOne(v, &arg1, "arg1", errp);
296
        qapi_dealloc_visitor_cleanup(md);
297
        return;
298
    }
299

    
300
    static void qmp_init_marshal(void)
301
    {
302
        qmp_register_command("my-command", qmp_marshal_input_my_command);
303
    }
304

    
305
    qapi_init(qmp_init_marshal);
306
    mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
307
    /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
308

    
309
    #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
310
    #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
311

    
312
    #include "example-qapi-types.h"
313
    #include "error.h"
314

    
315
    UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
316

    
317
    #endif
318
    mdroth@illuin:~/w/qemu2.git$