I tried to start some discussion on this topic previously, but it apparently didn't make it through the moderator, so I'm trying again having now joined the list.
I've recently taken an interest in the gowl <https://github.com/sebastianskejoe/gowl> implementation of the wayland protocol and noticed that the specification doesn't match the interface that gets generated by the wayland scanner. If I attempt to code-gen gowl using the wayland.xml file the wl_registry bind interface is missing a couple arguments that weston expects, resulting in the following runtime error: libwayland: message too short, object (2), message bind(usun) However, the spec indicates a bind request signature of "un". I tracked this down into some curious logic in the scanner and have been working on a patch to try and allow the corrected signature to be specified in the protocol. Unfortunately this has become more interesting then I'd anticipated. Attached is my naive attempt at resolving this issue. I'm horrified by the string->interface lookup and the wl_registry_bind api change but I'm not sure what else one can do. Any feedback or additional help would be appreciated. Note that this patch applies to the 1.5.91 tagged commit and compiles cleanly (for wayland). Weston didn't like having the lookup function defined in multiple files, so maybe there would be a better place to put such functionality. Thanks, Paul
From 4a5dfecc051c920835032b64434096f9403bd4f7 Mon Sep 17 00:00:00 2001 From: Paul Sbarra <sbarra.p...@gmail.com> Date: Wed, 3 Sep 2014 22:09:52 -0500 Subject: [PATCH] explicitly specify all registry bind request arguments --- protocol/wayland.xml | 5 ++++- src/scanner.c | 58 +++++++++++++++++++++++++++++-------------------- tests/test-compositor.c | 2 +- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/protocol/wayland.xml b/protocol/wayland.xml index bb457bc..e8a14f0 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -127,9 +127,12 @@ <request name="bind"> <description summary="bind an object to the display"> Binds a new, client-created object to the server using the - specified name as the identifier. + specified name as the identifier, and it implements the + given version of the given interface. </description> <arg name="name" type="uint" summary="unique name for the object"/> + <arg name="interface" type="string" summary="name of the object's interface"/> + <arg name="version" type="uint" summary="version of the object's interface"/> <arg name="id" type="new_id"/> </request> diff --git a/src/scanner.c b/src/scanner.c index 72fd3e8..a11ad45 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -356,7 +356,7 @@ start_element(void *data, const char *element_name, const char **atts) ctx->protocol->uppercase_name = uppercase_dup(name); ctx->protocol->description = NULL; } else if (strcmp(element_name, "copyright") == 0) { - + } else if (strcmp(element_name, "interface") == 0) { if (name == NULL) fail(&ctx->loc, "no interface name given"); @@ -704,11 +704,7 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) interface->name, interface->name); wl_list_for_each(a, &m->arg_list, link) { - if (a->type == NEW_ID && a->interface_name == NULL) { - printf(", const struct wl_interface *interface" - ", uint32_t version"); - continue; - } else if (a->type == NEW_ID) + if (a->type == NEW_ID) continue; printf(", "); emit_type(a); @@ -727,8 +723,15 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) interface->uppercase_name, m->uppercase_name); - if (ret->interface_name == NULL) - printf("interface"); + if (ret->interface_name == NULL) { + printf("string_to_interface("); + wl_list_for_each(a, &m->arg_list, link) { + if (a->type == STRING) { + printf("%s)", a->name); + break; + } + } + } else printf("&%s_interface", ret->interface_name); } else { @@ -741,8 +744,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) wl_list_for_each(a, &m->arg_list, link) { if (a->type == NEW_ID) { - if (a->interface_name == NULL) - printf(", interface->name, version"); printf(", NULL"); } else { printf(", %s", a->name); @@ -885,12 +886,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid "\t * %s - ", m->name); wl_list_for_each(a, &m->arg_list, link) { - if (side == SERVER && a->type == NEW_ID && - a->interface_name == NULL) - printf("\t * @interface: name of the objects interface\n" - "\t * @version: version of the objects interface\n"); - - desc_dump(a->summary ? a->summary : "(none)", "\t * @%s: ", a->name); } @@ -920,8 +915,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid if (side == SERVER && a->type == OBJECT) printf("struct wl_resource *"); - else if (side == SERVER && a->type == NEW_ID && a->interface_name == NULL) - printf("const char *interface, uint32_t version, uint32_t "); else if (side == CLIENT && a->type == OBJECT && a->interface_name == NULL) printf("void *"); @@ -997,7 +990,8 @@ emit_header(struct protocol *protocol, enum side side) "#include <stddef.h>\n" "#include \"%s\"\n\n" "struct wl_client;\n" - "struct wl_resource;\n\n", + "struct wl_resource;\n\n" + "extern const struct wl_interface* string_to_interface(const char* str);\n\n", protocol->uppercase_name, s, protocol->uppercase_name, s, (side == SERVER) ? "wayland-util.h" : "wayland-client.h"); @@ -1144,8 +1138,6 @@ emit_messages(struct wl_list *message_list, printf("i"); break; case NEW_ID: - if (a->interface_name == NULL) - printf("su"); printf("n"); break; case UNSIGNED: @@ -1187,14 +1179,16 @@ emit_code(struct protocol *protocol) { struct interface *i; struct wl_array types; - char **p, *prev; + char **p, *prev, first_pass; if (protocol->copyright) format_copyright(protocol->copyright); printf("#include <stdlib.h>\n" "#include <stdint.h>\n" - "#include \"wayland-util.h\"\n\n"); + "#include <string.h>\n" + "#include \"wayland-util.h\"\n\n" + "const struct wl_interface* string_to_interface(const char* str);\n\n"); wl_array_init(&types); wl_list_for_each(i, &protocol->interface_list, link) { @@ -1209,7 +1203,6 @@ emit_code(struct protocol *protocol) printf("extern const struct wl_interface %s_interface;\n", *p); prev = *p; } - wl_array_release(&types); printf("\n"); printf("static const struct wl_interface *types[] = {\n"); @@ -1220,6 +1213,23 @@ emit_code(struct protocol *protocol) } printf("};\n\n"); + printf("const struct wl_interface* string_to_interface(const char* str) {\n"); + printf("\tstruct wl_interface const *iface = NULL;\n\n"); + prev = NULL; + first_pass = 1; + wl_array_for_each(p, &types) { + if (prev && strcmp(*p, prev) == 0) + continue; + + printf(first_pass != 0 ? "\t" : "\telse "); + printf("if (strncmp(str, \"%s\", %zu) == 0)\n\t\tiface = &%s_interface;\n", *p, strlen(*p), *p); + first_pass = 0; + prev = *p; + } + printf("\treturn iface;\n}\n\n"); + wl_array_release(&types); + printf("\n"); + wl_list_for_each(i, &protocol->interface_list, link) { emit_messages(&i->request_list, i, "requests"); diff --git a/tests/test-compositor.c b/tests/test-compositor.c index 3248e2d..4382242 100644 --- a/tests/test-compositor.c +++ b/tests/test-compositor.c @@ -388,7 +388,7 @@ registry_handle_globals(void *data, struct wl_registry *registry, if (strcmp(intf, "test") != 0) return; - c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver); + c->tc = wl_registry_bind(registry, id, test_compositor_interface.name, ver); assert(c->tc && "Failed binding to registry"); wl_proxy_add_listener((struct wl_proxy *) c->tc, -- 2.1.0
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel