Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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 |
Stefan Weil | 4238e26 | 2011-11-13 22:24:27 +0100 | [diff] [blame] | 17 | scripts, paired with a separate schema, to generate |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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', |
Stefan Hajnoczi | acf8394 | 2011-10-28 15:58:26 +0100 | [diff] [blame] | 44 | 'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } } |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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' }, |
Stefan Hajnoczi | acf8394 | 2011-10-28 15:58:26 +0100 | [diff] [blame] | 66 | 'returns': 'str' } |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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 | { |
Paolo Bonzini | 3a86a0f | 2012-03-22 22:38:40 +0100 | [diff] [blame] | 197 | GenericList *i, **prev = (GenericList **)obj; |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 198 | |
| 199 | visit_start_list(m, name, errp); |
| 200 | |
Paolo Bonzini | 3a86a0f | 2012-03-22 22:38:40 +0100 | [diff] [blame] | 201 | for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) { |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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 | |
Paolo Bonzini | d195325 | 2012-07-17 16:17:04 +0200 | [diff] [blame] | 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). |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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 |
Stefan Weil | 2542bfd | 2011-08-28 21:45:40 +0200 | [diff] [blame] | 234 | convert QObjects received from the wire into |
Michael Roth | b84da83 | 2011-07-19 14:50:46 -0500 | [diff] [blame] | 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$ |