diff --git a/wayland/connection.c b/wayland/connection.c
index b53c0a1..782dd9e 100644
--- a/wayland/connection.c
+++ b/wayland/connection.c
@@ -686,7 +686,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target)
 	int i;
 
 	fprintf(stderr, "%s@%d.%s(",
-		target->interface->name, target->id,
+		target->interface->signature->name, target->id,
 		closure->message->name);
 
 	for (i = 2; i < closure->count; i++) {
@@ -707,7 +707,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target)
 		case 'o':
 			if (value->object)
 				fprintf(stderr, "%s@%u",
-					value->object->interface->name,
+					value->object->interface->signature->name,
 					value->object->id);
 			else
 				fprintf(stderr, "nil");
diff --git a/wayland/scanner.c b/wayland/scanner.c
index b6aebdb..9dd0669 100644
--- a/wayland/scanner.c
+++ b/wayland/scanner.c
@@ -325,34 +325,16 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 	/* We provide a hand written constructor for the display object */
 	if (strcmp(interface->name, "wl_display") != 0)
 		printf("static inline struct %s *\n"
-		       "%s_create(struct wl_display *display, uint32_t id, uint32_t version)\n"
+		       "%s_create(struct wl_display *display, struct %s_listener *listener, uint32_t id, void *data)\n"
 		       "{\n"
-		       "\twl_display_bind(display, id, \"%s\", version);\n\n"
 		       "\treturn (struct %s *)\n"
-		       "\t\twl_proxy_create_for_id(display, &%s_interface, id);\n"
+		       "\t\twl_proxy_create_for_id(display, &listener->interface, id, data);\n"
 		       "}\n\n",
 		       interface->name,
 		       interface->name,
 		       interface->name,
-		       interface->name,
 		       interface->name);
 
-	printf("static inline void\n"
-	       "%s_set_user_data(struct %s *%s, void *user_data)\n"
-	       "{\n"
-	       "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
-	       "}\n\n",
-	       interface->name, interface->name, interface->name,
-	       interface->name);
-
-	printf("static inline void *\n"
-	       "%s_get_user_data(struct %s *%s)\n"
-	       "{\n"
-	       "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
-	       "}\n\n",
-	       interface->name, interface->name, interface->name,
-	       interface->name);
-
 	has_destructor = 0;
 	has_destroy = 0;
 	wl_list_for_each(m, message_list, link) {
@@ -493,12 +475,10 @@ emit_structs(struct wl_list *message_list, struct interface *interface)
 	struct arg *a;
 	int is_interface, n;
 
-	if (wl_list_empty(message_list))
-		return;
-
 	is_interface = message_list == &interface->request_list;
-	printf("struct %s_%s {\n", interface->name,
-	       is_interface ? "interface" : "listener");
+	printf("struct %s_%s {\n"
+	       "\tstruct wl_interface interface;\n",
+	       interface->name, is_interface ? "interface" : "listener");
 
 	wl_list_for_each(m, message_list, link) {
 		printf("\tvoid (*%s)(", m->name);
@@ -526,21 +506,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface)
 	}
 
 	printf("};\n\n");
-
-	if (!is_interface) {
-	    printf("static inline int\n"
-		   "%s_add_listener(struct %s *%s,\n"
-		   "%sconst struct %s_listener *listener, void *data)\n"
-		   "{\n"
-		   "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
-		   "%s(void (**)(void)) listener, data);\n"
-		   "}\n\n",
-		   interface->name, interface->name, interface->name,
-		   indent(17 + strlen(interface->name)),
-		   interface->name,
-		   interface->name,
-		   indent(37));
-	}
 }
 
 
@@ -571,8 +536,8 @@ emit_header(struct protocol *protocol, int server)
 	printf("\n");
 
 	wl_list_for_each(i, &protocol->interface_list, link) {
-		printf("extern const struct wl_interface "
-		       "%s_interface;\n",
+		printf("extern const struct wl_signature "
+		       "%s_signature;\n",
 		       i->name);
 	}
 	printf("\n");
@@ -662,8 +627,8 @@ emit_code(struct protocol *protocol)
 		emit_messages(&i->request_list, i, "requests");
 		emit_messages(&i->event_list, i, "events");
 
-		printf("WL_EXPORT const struct wl_interface "
-		       "%s_interface = {\n"
+		printf("WL_EXPORT const struct wl_signature "
+		       "%s_signature = {\n"
 		       "\t\"%s\", %d,\n",
 		       i->name, i->name, i->version);
 
diff --git a/wayland/wayland-client.c b/wayland/wayland-client.c
index 531807d..8b703b3 100644
--- a/wayland/wayland-client.c
+++ b/wayland/wayland-client.c
@@ -139,7 +139,7 @@ wl_display_remove_global_listener(struct wl_display *display,
 
 WL_EXPORT struct wl_proxy *
 wl_proxy_create_for_id(struct wl_display *display,
-		       const struct wl_interface *interface, uint32_t id)
+		       const struct wl_interface *interface, uint32_t id, void *data)
 {
 	struct wl_proxy *proxy;
 
@@ -148,9 +148,9 @@ wl_proxy_create_for_id(struct wl_display *display,
 		return NULL;
 
 	proxy->object.interface = interface;
-	proxy->object.implementation = NULL;
 	proxy->object.id = id;
 	proxy->display = display;
+	proxy->user_data = data;
 	wl_hash_table_insert(display->objects, proxy->object.id, proxy);
 
 	return proxy;
@@ -158,10 +158,11 @@ wl_proxy_create_for_id(struct wl_display *display,
 
 WL_EXPORT struct wl_proxy *
 wl_proxy_create(struct wl_proxy *factory,
-		const struct wl_interface *interface)
+		const struct wl_interface *interface, void *data)
 {
 	return wl_proxy_create_for_id(factory->display, interface,
-				      wl_display_allocate_id(factory->display));
+				      wl_display_allocate_id(factory->display),
+				      data);
 }
 
 WL_EXPORT void
@@ -171,31 +172,18 @@ wl_proxy_destroy(struct wl_proxy *proxy)
 	free(proxy);
 }
 
-WL_EXPORT int
-wl_proxy_add_listener(struct wl_proxy *proxy,
-		      void (**implementation)(void), void *data)
-{
-	if (proxy->object.implementation) {
-		fprintf(stderr, "proxy already has listener\n");
-		return -1;
-	}
-
-	proxy->object.implementation = implementation;
-	proxy->user_data = data;
-
-	return 0;
-}
-
 WL_EXPORT void
 wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 {
 	struct wl_closure *closure;
+	const struct wl_signature *signature;
 	va_list ap;
 
 	va_start(ap, opcode);
+	signature = proxy->object.interface->signature;
 	closure = wl_connection_vmarshal(proxy->display->connection,
 					 &proxy->object, opcode, ap,
-					 &proxy->object.interface->methods[opcode]);
+					 &signature->methods[opcode]);
 	va_end(ap);
 
 	wl_closure_send(closure, proxy->display->connection);
@@ -214,7 +202,8 @@ add_visual(struct wl_display *display, uint32_t id)
 	struct wl_visual *visual;
 
 	visual = (struct wl_visual *)
-		wl_proxy_create_for_id(display, &wl_visual_interface, id);
+		wl_proxy_create_for_id(display,
+				       &wl_visual_interface, id, NULL);
 	if (display->argb_visual == NULL)
 		display->argb_visual = visual;
 	else if (display->premultiplied_argb_visual == NULL)
@@ -345,6 +334,7 @@ display_handle_key(void *data,
 }
 
 static const struct wl_display_listener display_listener = {
+	{ &wl_display_signature },
 	display_handle_invalid_object,
 	display_handle_invalid_method,
 	display_handle_no_memory,
@@ -435,17 +425,14 @@ wl_display_connect(const char *name)
 	wl_list_init(&display->global_listener_list);
 	wl_list_init(&display->global_list);
 
-	display->proxy.object.interface = &wl_display_interface;
+	display->proxy.object.interface = &display_listener.interface;
 	display->proxy.object.id = 1;
 	display->proxy.display = display;
+	display->proxy.user_data = display;
 
 	wl_list_init(&display->sync_list);
 	wl_list_init(&display->frame_list);
 
-	display->proxy.object.implementation =
-		(void(**)(void)) &display_listener;
-	display->proxy.user_data = display;
-
 	display->connection = wl_connection_create(display->fd,
 						   connection_update,
 						   display);
@@ -532,6 +519,7 @@ handle_event(struct wl_display *display,
 	struct wl_proxy *proxy;
 	struct wl_closure *closure;
 	const struct wl_message *message;
+	const struct wl_signature *signature;
 
 	wl_connection_copy(display->connection, p, size);
 	if (id == 1)
@@ -539,12 +527,13 @@ handle_event(struct wl_display *display,
 	else
 		proxy = wl_hash_table_lookup(display->objects, id);
 
-	if (proxy == NULL || proxy->object.implementation == NULL) {
+	if (proxy == NULL) {
 		wl_connection_consume(display->connection, size);
 		return;
 	}
 
-	message = &proxy->object.interface->events[opcode];
+	signature = proxy->object.interface->signature;
+	message = &signature->events[opcode];
 	closure = wl_connection_demarshal(display->connection,
 					  size, display->objects, message);
 
@@ -552,7 +541,7 @@ handle_event(struct wl_display *display,
 		wl_closure_print(closure, &proxy->object);
 
 	wl_closure_invoke(closure, &proxy->object,
-			  proxy->object.implementation[opcode],
+			  proxy->object.interface->funcs[opcode],
 			  proxy->user_data);
 
 	wl_closure_destroy(closure);
@@ -605,15 +594,3 @@ wl_display_allocate_id(struct wl_display *display)
 
 	return display->id++;
 }
-
-WL_EXPORT void
-wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
-{
-	proxy->user_data = user_data;
-}
-
-WL_EXPORT void *
-wl_proxy_get_user_data(struct wl_proxy *proxy)
-{
-	return proxy->user_data;
-}
diff --git a/wayland/wayland-client.h b/wayland/wayland-client.h
index f1ac797..cd6e440 100644
--- a/wayland/wayland-client.h
+++ b/wayland/wayland-client.h
@@ -34,15 +34,13 @@ struct wl_display;
 
 void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
 struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
-				 const struct wl_interface *interface);
+				 const struct wl_interface *interface,
+				 void *data);
 struct wl_proxy *wl_proxy_create_for_id(struct wl_display *display,
 					const struct wl_interface *interface,
-					uint32_t id);
+					uint32_t id,
+					void *data);
 void wl_proxy_destroy(struct wl_proxy *proxy);
-int wl_proxy_add_listener(struct wl_proxy *proxy,
-			  void (**implementation)(void), void *data);
-void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);
-void *wl_proxy_get_user_data(struct wl_proxy *proxy);
 
 #include "wayland-client-protocol.h"
 
diff --git a/wayland/wayland-server.c b/wayland/wayland-server.c
index daa6989..d5ac92d 100644
--- a/wayland/wayland-server.c
+++ b/wayland/wayland-server.c
@@ -95,12 +95,14 @@ wl_client_post_event(struct wl_client *client, struct wl_object *sender,
 		     uint32_t opcode, ...)
 {
 	struct wl_closure *closure;
+	const struct wl_signature *signature;
 	va_list ap;
 
 	va_start(ap, opcode);
+	signature = sender->interface->signature;
 	closure = wl_connection_vmarshal(client->connection,
 					 sender, opcode, ap,
-					 &sender->interface->events[opcode]);
+					 &signature->events[opcode]);
 	va_end(ap);
 
 	wl_closure_send(closure, client->connection);
@@ -120,6 +122,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 	struct wl_connection *connection = client->connection;
 	struct wl_object *object;
 	struct wl_closure *closure;
+	const struct wl_signature *signature;
 	const struct wl_message *message;
 	uint32_t p[2], opcode, size;
 	uint32_t cmask = 0;
@@ -152,7 +155,8 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 			continue;
 		}
 
-		if (opcode >= object->interface->method_count) {
+		signature = object->interface->signature;
+		if (opcode >= signature->method_count) {
 			wl_client_post_event(client, &client->display->object,
 					     WL_DISPLAY_INVALID_METHOD, p[0], opcode);
 			wl_connection_consume(connection, size);
@@ -160,7 +164,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 			continue;
 		}
 
-		message = &object->interface->methods[opcode];
+		message = &signature->methods[opcode];
 		closure = wl_connection_demarshal(client->connection, size,
 						  client->display->objects,
 						  message);
@@ -181,7 +185,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 			wl_closure_print(closure, object);
 
 		wl_closure_invoke(closure, object,
-				  object->implementation[opcode], client);
+				  object->interface->funcs[opcode], client);
 
 		wl_closure_destroy(closure);
 	}
@@ -276,12 +280,15 @@ wl_client_post_no_memory(struct wl_client *client)
 WL_EXPORT void
 wl_client_post_global(struct wl_client *client, struct wl_object *object)
 {
+	const struct wl_signature *signature;
+
+	signature = object->interface->signature;
 	wl_client_post_event(client,
 			     &client->display->object,
 			     WL_DISPLAY_GLOBAL,
 			     object,
-			     object->interface->name,
-			     object->interface->version);
+			     signature->name,
+			     signature->version);
 }
 
 WL_EXPORT void
@@ -524,6 +531,7 @@ display_frame(struct wl_client *client,
 }
 
 struct wl_display_interface display_interface = {
+	{ &wl_display_signature },
 	display_bind,
 	display_sync,
 	display_frame
@@ -562,12 +570,10 @@ wl_display_create(void)
 	wl_list_init(&display->socket_list);
 
 	display->client_id_range = 256; /* Gah, arbitrary... */
-
 	display->id = 1;
-	display->object.interface = &wl_display_interface;
-	display->object.implementation = (void (**)(void)) &display_interface;
-	wl_display_add_object(display, &display->object);
-	if (wl_display_add_global(display, &display->object, NULL)) {
+
+	if (wl_display_add_global(display, &display->object,
+				  &display_interface.interface, NULL)) {
 		wl_hash_table_destroy(display->objects);
 		wl_event_loop_destroy(display->loop);
 		free(display);
@@ -597,15 +603,18 @@ wl_display_destroy(struct wl_display *display)
 }
 
 WL_EXPORT void
-wl_display_add_object(struct wl_display *display, struct wl_object *object)
+wl_display_add_object(struct wl_display *display, struct wl_object *object,
+		      const struct wl_interface *interface)
 {
+	object->interface = interface;
 	object->id = display->id++;
 	wl_hash_table_insert(display->objects, object->id, object);
 }
 
 WL_EXPORT int
-wl_display_add_global(struct wl_display *display,
-		      struct wl_object *object, wl_global_bind_func_t func)
+wl_display_add_global(struct wl_display *display, struct wl_object *object, 
+		      const struct wl_interface *interface,
+		      wl_global_bind_func_t func)
 {
 	struct wl_global *global;
 
@@ -613,6 +622,7 @@ wl_display_add_global(struct wl_display *display,
 	if (global == NULL)
 		return -1;
 
+	wl_display_add_object(display, object, interface);
 	global->object = object;
 	global->func = func;
 	wl_list_insert(display->global_list.prev, &global->link);
@@ -786,39 +796,30 @@ wl_display_add_socket(struct wl_display *display, const char *name)
 	return 0;
 }
 
+static const struct wl_interface visual_interface = {
+	&wl_visual_signature
+};
+
 WL_EXPORT int
 wl_compositor_init(struct wl_compositor *compositor,
 		   const struct wl_compositor_interface *interface,
 		   struct wl_display *display)
 {
-	compositor->object.interface = &wl_compositor_interface;
-	compositor->object.implementation = (void (**)(void)) interface;
-	wl_display_add_object(display, &compositor->object);
-	if (wl_display_add_global(display, &compositor->object, NULL))
+	if (wl_display_add_global(display, &compositor->object,
+				  &interface->interface, NULL))
 		return -1;
 
-	compositor->argb_visual.object.interface = &wl_visual_interface;
-	compositor->argb_visual.object.implementation = NULL;
-	wl_display_add_object(display, &compositor->argb_visual.object);
-	if (wl_display_add_global(display, &compositor->argb_visual.object, NULL))
+	if (wl_display_add_global(display, &compositor->argb_visual.object,
+				  &visual_interface, NULL))
 		return -1;
 
-	compositor->premultiplied_argb_visual.object.interface =
-		&wl_visual_interface;
-	compositor->premultiplied_argb_visual.object.implementation = NULL;
-	wl_display_add_object(display,
-			      &compositor->premultiplied_argb_visual.object);
 	if (wl_display_add_global(display,
 				  &compositor->premultiplied_argb_visual.object,
-				  NULL))
+				  &visual_interface, NULL))
 		return -1;
 
-	compositor->rgb_visual.object.interface = &wl_visual_interface;
-	compositor->rgb_visual.object.implementation = NULL;
-	wl_display_add_object(display,
-			      &compositor->rgb_visual.object);
-	if (wl_display_add_global(display,
-				  &compositor->rgb_visual.object, NULL))
+	if (wl_display_add_global(display, &compositor->rgb_visual.object,
+				  &visual_interface, NULL))
 		return -1;
 
 	return 0;
diff --git a/wayland/wayland-server.h b/wayland/wayland-server.h
index 649bb6b..414ceff 100644
--- a/wayland/wayland-server.h
+++ b/wayland/wayland-server.h
@@ -83,14 +83,16 @@ void wl_display_terminate(struct wl_display *display);
 void wl_display_run(struct wl_display *display);
 
 void wl_display_add_object(struct wl_display *display,
-			   struct wl_object *object);
+			   struct wl_object *object,
+			   const struct wl_interface *interface);
 
 typedef void (*wl_global_bind_func_t)(struct wl_client *client,
 				      struct wl_object *global,
 				      uint32_t version);
 
 int wl_display_add_global(struct wl_display *display,
-			  struct wl_object *object,
+			  struct wl_object *object, 
+			  const struct wl_interface *interface,
 			  wl_global_bind_func_t func);
 
 struct wl_client *wl_client_create(struct wl_display *display, int fd);
diff --git a/wayland/wayland-shm.c b/wayland/wayland-shm.c
index 5f46293..36df029 100644
--- a/wayland/wayland-shm.c
+++ b/wayland/wayland-shm.c
@@ -75,6 +75,7 @@ shm_buffer_destroy(struct wl_client *client, struct wl_buffer *buffer)
 }
 
 const static struct wl_buffer_interface shm_buffer_interface = {
+	{ &wl_buffer_signature },
 	shm_buffer_damage,
 	shm_buffer_destroy
 };
@@ -98,10 +99,7 @@ wl_shm_buffer_init(struct wl_shm *shm, uint32_t id,
 	buffer->data = data;
 
 	buffer->buffer.resource.object.id = id;
-	buffer->buffer.resource.object.interface = &wl_buffer_interface;
-	buffer->buffer.resource.object.implementation = (void (**)(void))
-		&shm_buffer_interface;
-
+	buffer->buffer.resource.object.interface = &shm_buffer_interface.interface;
 	buffer->buffer.resource.destroy = destroy_buffer;
 
 	buffer->shm = shm;
@@ -123,7 +121,7 @@ shm_create_buffer(struct wl_client *client, struct wl_shm *shm,
 
 	/* FIXME: Define a real exception event instead of abusing the
 	 * display.invalid_object error */
-	if (visual->object.interface != &wl_visual_interface) {
+	if (visual->object.interface->signature != &wl_visual_signature) {
 		wl_client_post_event(client, (struct wl_object *) display,
 				     WL_DISPLAY_INVALID_OBJECT, 0);
 		fprintf(stderr, "invalid visual in create_buffer\n");
@@ -166,6 +164,7 @@ shm_create_buffer(struct wl_client *client, struct wl_shm *shm,
 }
 
 const static struct wl_shm_interface shm_interface = {
+	{ &wl_shm_signature },
 	shm_create_buffer
 };
 
@@ -180,10 +179,8 @@ wl_shm_init(struct wl_display *display,
 	if (!shm)
 		return NULL;
 
-	shm->object.interface = &wl_shm_interface;
-	shm->object.implementation = (void (**)(void)) &shm_interface;
-	wl_display_add_object(display, &shm->object);
-	wl_display_add_global(display, &shm->object, NULL);
+	wl_display_add_global(display, &shm->object,
+			      &shm_interface.interface, NULL);
 
 	shm->callbacks = callbacks;
 
@@ -201,8 +198,8 @@ wl_shm_finish(struct wl_shm *shm)
 WL_EXPORT int
 wl_buffer_is_shm(struct wl_buffer *buffer)
 {
-	return buffer->resource.object.implementation == 
-		(void (**)(void)) &shm_buffer_interface;
+	return buffer->resource.object.interface ==
+		&shm_buffer_interface.interface;
 }
 
 WL_EXPORT int32_t
diff --git a/wayland/wayland-util.h b/wayland/wayland-util.h
index 6c1231a..6114c5a 100644
--- a/wayland/wayland-util.h
+++ b/wayland/wayland-util.h
@@ -55,7 +55,7 @@ struct wl_message {
 	const void **types;
 };
 
-struct wl_interface {
+struct wl_signature {
 	const char *name;
 	int version;
 	int method_count;
@@ -64,9 +64,13 @@ struct wl_interface {
 	const struct wl_message *events;
 };
 
+struct wl_interface {
+	const struct wl_signature *signature;
+	void *funcs[0];
+};
+
 struct wl_object {
 	const struct wl_interface *interface;
-	void (**implementation)(void);
 	uint32_t id;
 };
 
