Statistics
| Branch: | Revision:

root / docs / qapi-code-gen.txt @ 2542bfd5

History | View | Annotate | Download (10.9 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 seperate 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;
198

    
199
        visit_start_list(m, name, errp);
200

    
201
        for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
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

    
224
=== scripts/qapi-commands.py ===
225

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

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

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

    
241
Example:
242

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

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

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

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

    
268

    
269
        *ret_out = qmp_output_get_qobject(mo);
270
    }
271

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

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

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

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

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

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

    
307
    #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
308
    #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
309

    
310
    #include "example-qapi-types.h"
311
    #include "error.h"
312

    
313
    UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
314

    
315
    #endif
316
    mdroth@illuin:~/w/qemu2.git$