[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v1][ 21/21] qapi: add QAPI code generation docum
From: |
Lluís |
Subject: |
Re: [Qemu-devel] [PATCH v1][ 21/21] qapi: add QAPI code generation documentation |
Date: |
Thu, 02 Jun 2011 15:25:50 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) |
Here go some minor text corrections.
Michael Roth writes:
> Signed-off-by: Michael Roth <address@hidden>
> ---
> docs/qapi-code-gen.txt | 315
> ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 315 insertions(+), 0 deletions(-)
> create mode 100644 docs/qapi-code-gen.txt
> diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
> new file mode 100644
> index 0000000..1ba7a9e
> --- /dev/null
> +++ b/docs/qapi-code-gen.txt
> @@ -0,0 +1,315 @@
> += How to use the QAPI code generator =
> +
> +* Note: as of this writing, QMP does not use QAPI. Eventually QMP
> +commands will be converted to use QAPI internally. The following
> +information describes QMP/QAPI as it will exist afterward the
> +conversion.
> +
> +QAPI is a native C API within QEMU which provides management-level
> +functionality to internal/external users. For external
> +users/processes, this interface is made available by a JSON-based
> +QEMU Monitor protocol which provided by the QMP server.
s/which provided/that is provided/
> +
> +To map QMP-defined interfaces to the native C QAPI implementations,
> +and JSON-based schema is used to define types and function
s/and JSON-based/a JSON-based/
> +signatures, and a set of scripts is used to generate types/signatures,
> +and marshaling/dispatch code. The QEMU Guest Agent also uses these
> +scripts, paired with a seperate schema, to generate
> +marshaling/dispatch code for the guest agent server running in the
> +guest.
> +
> +This document will describe how the schemas, scripts, and resulting
> +code is used.
> +
> +
> +== QMP/Guest agent schema ==
> +
> +This file defines the types, commands, and events used by QMP. It should
> +fully describe the interface used by QMP.
> +
> +This file is designed to be loosely based on JSON although it's technical
s/technical/technically/
> +executable Python. While dictionaries are used, they are parsed as
> +OrderedDicts so that ordering is preserved.
Valid data types should probably be explained/listed.
> +
> +There are two basic syntaxes used. The first syntax defines a type and is
> +represented by a dictionary. There are three kinds of types that are
> +supported.
> +
> +A complex type is a dictionary containing a single key who's value is a
> +dictionary. This corresponds to a struct in C or an Object in JSON. An
> +example of a complex type is:
> +
> + { 'type': 'MyType',
> + 'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } }
> +
> +The use of '*' as a prefix to the name means the member is optional.
> Optional
> +members should always be added to the end of the dictionary to preserve
> +backwards compatibility.
> +
> +An enumeration type is a dictionary containing a single key who's value is a
> +list of strings. An example enumeration is:
> +
> + { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
> +
> +Generally speaking, complex types and enums should always use CamelCase for
> +the type names.
> +
> +Commands are defined by using a list containing three members. The first
> +member is the command name, the second member is a dictionary containing
> +arguments, and the third member is the return type.
> +
> +An example command is:
> +
> + { 'command': 'my-command',
> + 'data': { 'arg1': 'str', '*arg2': 'str' },
> + 'returns': 'str' ]
> +
> +Command names should be all lower case with words separated by a hyphen.
> +
> +
> +== Code generation ==
> +
> +Schemas are fed into 3 scripts to generate all the code/files that, paired
> +with the core QAPI libraries, comprise everything required to take JSON
> +commands read in by a QMP/guest agent server, unmarshal the arguments into
> +the underlying C types, call into the corresponding C function, and map the
> +response back to a QMP/guest agent response to be returned to the user.
> +
> +For example usage, we'll use the following schema, which describes a single
s/For example usage/As an (usage )example/
> +complex user-defined type (which will produce a C struct, along with a list
> +node structure that can be used to chain together a list of such types in
> +case we want to accept/return a list of this type with a command), and a
> +command which takes that type as a parameter and returns the same type:
> +
> + address@hidden:~/w/qemu2.git$ cat example-schema.json
> + { 'type': 'UserDefOne',
> + 'data': { 'integer': 'int', 'string': 'str' } }
> +
> + { 'commands': 'my-command',
s/commands/command/
> + 'data': {'arg1': 'UserDefOne'},
> + 'returns': 'UserDefOne' }
> + address@hidden:~/w/qemu2.git$
> +
> +=== scripts/qapi-types.py ===
> +
> +Used to generate the C types defined by a schema. The following files are
> +created:
> +
> +$(prefix)qapi-types.h - C types corresponding to types defined in
> + the schema you pass in
> +$(prefix)qapi-types.c - Cleanup functions for the above C types
> +
> +The $(prefix) is an optional parameter used to as a namespace to keep the
s/used to as/used as/
> +generated code from one schema/code-generation separated from others so code
> +can be generated/used from multiple schemas without clobbering previously
> +created code.
> +
> +Example:
> +
> + address@hidden:~/w/qemu2.git$ python scripts/qapi-types.py \
> + --output-dir="qapi-generated" --prefix="example-" < example-schema.json
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
> + /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> + #include "qapi/qapi-dealloc-visiter.h"
> + #include "example-qapi-types.h"
> + #include "example-qapi-visit.h"
> +
> + void qapi_free_UserDefOne(UserDefOne * obj)
> + {
> + QapiDeallocVisiter *md;
> + Visiter *v;
> +
> + if (!obj) {
> + return;
> + }
> +
> + md = qapi_dealloc_visiter_new();
> + v = qapi_dealloc_get_visiter(md);
> + visit_type_UserDefOne(v, &obj, NULL, NULL);
> + qapi_dealloc_visiter_cleanup(md);
> + }
> +
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
> + /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
> + #ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
> + #define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
> +
> + #include "qapi/qapi-types-core.h"
> +
> + typedef struct UserDefOne UserDefOne;
> +
> + typedef struct UserDefOneList
> + {
> + UserDefOne *value;
> + struct UserDefOneList *next;
> + } UserDefOneList;
> +
> + struct UserDefOne
> + {
> + int64_t integer;
> + char * string;
> + };
> +
> + void qapi_free_UserDefOne(UserDefOne * obj);
> +
> + #endif
> +
> +
> +=== scripts/qapi-visit.py ===
> +
> +Used to generate the visiter functions used to walk through and convert
> +a QObject (as provided by QMP) to a native C data structure and
> +vice-versa, as well as the visiter function used to dealloc a complex
> +schema-defined C type.
> +
> +The following files are generated:
> +
> +$(prefix)qapi-visit.c: visiter function for a particular c type, used
s/c type/C type/
> + to automagically convert qobjects into the
s/qobjects/QObjects/
> + corresponding C type and vice-versa, as well
> + as for deallocating memory for an existing C
> + type
> +
> +$(prefix)qapi-visit.h: declarations for previously mentioned visiter
> + functions
> +
> +Example:
> +
> + address@hidden:~/w/qemu2.git$ python scripts/qapi-visit.py \
> + --output-dir="qapi-generated" --prefix="example-" <
> example-schema.json
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
> + /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> + #include "example-qapi-visit.h"
> +
> + void visit_type_UserDefOne(Visiter *m, UserDefOne ** obj, const char
> *name, Error **errp)
> + {
> + visit_start_struct(m, (void **)obj, "UserDefOne", name, errp);
> + visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL,
> "integer", errp);
> + visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string",
> errp);
> + visit_end_struct(m, errp);
> + }
> +
> + void visit_type_UserDefOneList(Visiter *m, UserDefOneList ** obj, const
> char *name, Error **errp)
> + {
> + GenericList *i;
> +
> + visit_start_list(m, name, errp);
> +
> + for (i = visit_next_list(m, (GenericList **)obj, errp); i; i =
> visit_next_list(m, &i, errp)) {
> + UserDefOneList *native_i = (UserDefOneList *)i;
> + visit_type_UserDefOne(m, &native_i->value, NULL, errp);
> + }
> +
> + visit_end_list(m, errp);
> + }
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
> + /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> + #ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
> + #define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
> +
> + #include "qapi/qapi-visit-core.h"
> + #include "example-qapi-types.h"
> +
> + void visit_type_UserDefOne(Visiter *m, UserDefOne ** obj, const char
> *name, Error **errp);
> + void visit_type_UserDefOneList(Visiter *m, UserDefOneList ** obj, const
> char *name, Error **errp);
> +
> + #endif
> + address@hidden:~/w/qemu2.git$
> +
> +
> +=== scripts/qapi-commands.py ===
> +
> +Used to generate the marshaling/dispatch functions for the commands defined
> +in the schema. The following files are generated:
> +
> +$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
> + QMP command defined in the schema. Functions
> + generated by qapi-visit.py are used to
> + convert qobjects recieved from the wire into
s/qobjects/QObjects/
> + function parameters, and uses the same
> + visiter functions to convert native C return
> + values to qobjects from transmission back
s/qobjects/QObjects/
> + over the wire.
> +
> +$(prefix)qmp-commands.h: Function prototypes for the QMP commands
> + specified in the schema.
> +
> +Example:
> +
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
> + /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> + #include "qemu-objects.h"
> + #include "qapi/qmp-core.h"
> + #include "qapi/qapi-visit-core.h"
> + #include "qapi/qmp-output-visiter.h"
> + #include "qapi/qmp-input-visiter.h"
> + #include "qapi/qapi-dealloc-visiter.h"
> + #include "example-qapi-types.h"
> + #include "example-qapi-visit.h"
> +
> + #include "example-qmp-commands.h"
> + static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject
> **ret_out, Error **errp)
> + {
> + QapiDeallocVisiter *md = qapi_dealloc_visiter_new();
> + QmpOutputVisiter *mo = qmp_output_visiter_new();
> + Visiter *v;
> +
> + v = qmp_output_get_visiter(mo);
> + visit_type_UserDefOne(v, &ret_in, "unused", errp);
> + v = qapi_dealloc_get_visiter(md);
> + visit_type_UserDefOne(v, &ret_in, "unused", errp);
> + qapi_dealloc_visiter_cleanup(md);
> +
> +
> + *ret_out = qmp_output_get_qobject(mo);
> + }
> +
> + static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict
> *args, QObject **ret, Error **errp)
> + {
> + UserDefOne * retval = NULL;
> + QmpInputVisiter *mi;
> + QapiDeallocVisiter *md;
> + Visiter *v;
> + UserDefOne * arg1 = NULL;
> +
> + mi = qmp_input_visiter_new(QOBJECT(args));
> + v = qmp_input_get_visiter(mi);
> + visit_type_UserDefOne(v, &arg1, "arg1", errp);
> +
> + if (error_is_set(errp)) {
> + goto out;
> + }
> + retval = qmp_my_command(arg1, errp);
> + qmp_marshal_output_my_command(retval, ret, errp);
> +
> + out:
> + md = qapi_dealloc_visiter_new();
> + v = qapi_dealloc_get_visiter(md);
> + visit_type_UserDefOne(v, &arg1, "arg1", errp);
> + qapi_dealloc_visiter_cleanup(md);
> + return;
> + }
> +
> + static void qmp_init_marshal(void)
> + {
> + qmp_register_command("my-command", qmp_marshal_input_my_command);
> + }
> +
> + qapi_init(qmp_init_marshal);
> + address@hidden:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
> + /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> + #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
> + #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
> +
> + #include "example-qapi-types.h"
> + #include "error.h"
> +
> + UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
> +
> + #endif
> + address@hidden:~/w/qemu2.git$
> --
> 1.7.0.4
--
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth
- [Qemu-devel] [PATCH v1][ 05/21] qapi: add qapi-types.py code generator, (continued)
- [Qemu-devel] [PATCH v1][ 05/21] qapi: add qapi-types.py code generator, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 06/21] qapi: add qapi-visit.py code generator, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 15/21] qapi: add base declaration/types for QMP, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 16/21] qapi: test schema used for unit tests, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 17/21] qapi: add test-visiter, tests for gen. visiter code, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 18/21] qapi: Makefile changes to build test-visiter, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 10/21] qapi: add QMP input visiter, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 11/21] qapi: add QMP output visiter, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 09/21] qapi: add qapi-visit-core.h, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 21/21] qapi: add QAPI code generation documentation, Michael Roth, 2011/06/01
- Re: [Qemu-devel] [PATCH v1][ 21/21] qapi: add QAPI code generation documentation,
Lluís <=
- [Qemu-devel] [PATCH v1][ 08/21] qapi: add qapi-types-core.h, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 20/21] qapi: Makefile changes to build test-qmp-commands, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 02/21] qlist: add qlist_first()/qlist_next(), Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 01/21] Add hard build dependency on glib, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 07/21] qapi: add qapi-commands.py code generator, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 03/21] qapi: add module init types for qapi, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 13/21] qapi: add command registration/lookup functions, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 04/21] qapi: add ordereddict/qapi.py helper libraries, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 14/21] qapi: add QMP dispatch functions, Michael Roth, 2011/06/01
- [Qemu-devel] [PATCH v1][ 12/21] qapi: add QAPI dealloc visiter, Michael Roth, 2011/06/01