wayland学习(1)-协议解析工具实现

本文详细介绍了Wayland核心协议解析工具wayland-scanner的工作原理,通过对源码的分析,展示了如何从wayland.xml生成客户端和服务器端的头文件及代码。内容包括生成头文件的函数emit_header、接口类型的保存、接口结构体定义、事件和请求的处理函数生成等,深入解析了wayland-scanner生成client和server端代码的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 wayland核心协议为wayland/protocol/wayland.xml,其中部分代码如下所示:

  <interface name="wl_display" version="1">
    <description summary="core global object">
      The core global object.  This is a special singleton object.  It
      is used for internal Wayland protocol features.
    </description>

    <request name="sync">
      <description summary="asynchronous roundtrip">
	The sync request asks the server to emit the 'done' event
	on the returned wl_callback object.  Since requests are
	handled in-order and events are delivered in-order, this can
	be used as a barrier to ensure all previous requests and the
	resulting events have been handled.

	The object returned by this request will be destroyed by the
	compositor after the callback is fired and as such the client must not
	attempt to use it after that point.

	The callback_data passed in the callback is the event serial.
      </description>
      <arg name="callback" type="new_id" interface="wl_callback"
	   summary="callback object for the sync request"/>
    </request>

    <request name="get_registry">
      <description summary="get global registry object">
	This request creates a registry object that allows the client
	to list and bind the global objects available from the
	compositor.

	It should be noted that the server side resources consumed in
	response to a get_registry request can only be released when the
	client disconnects, not when the client side proxy is destroyed.
	Therefore, clients should invoke get_registry as infrequently as
	possible to avoid wasting memory.
      </description>
      <arg name="registry" type="new_id" interface="wl_registry"
	   summary="global registry object"/>
    </request>

    <event name="error">
      <description summary="fatal error event">
	The error event is sent out when a fatal (non-recoverable)
	error has occurred.  The object_id argument is the object
	where the error occurred, most often in response to a request
	to that object.  The code identifies the error and is defined
	by the object interface.  As such, each interface defines its
	own set of error codes.  The message is a brief description
	of the error, for (debugging) convenience.
      </description>
      <arg name="object_id" type="object" summary="object where the error occurred"/>
      <arg name="code" type="uint" summary="error code"/>
      <arg name="message" type="string" summary="error description"/>
    </event>

    <enum name="error">
      <description summary="global error values">
	These errors are global and can be emitted in response to any
	server request.
      </description>
      <entry name="invalid_object" value="0"
	     summary="server couldn't find object"/>
      <entry name="invalid_method" value="1"
	     summary="method doesn't exist on the specified interface"/>
      <entry name="no_memory" value="2"
	     summary="server is out of memory"/>
    </enum>

    <event name="delete_id">
      <description summary="acknowledge object ID deletion">
	This event is used internally by the object ID management
	logic.  When a client deletes an object, the server will send
	this event to acknowledge that it has seen the delete request.
	When the client receives this event, it will know that it can
	safely reuse the object ID.
      </description>
      <arg name="id" type="uint" summary="deleted object ID"/>
    </event>
  </interface>

        通过wayland自带工具wayland-scanner可以生成wayland-client-protocol.h,wayland-protocol.c,wayland-server-protocol.h三个文件,该工具的具体实现为wayland/src/scanner.c,下面对其实现进行具体分析。

        代码中定义了以下几个主要类型:

struct protocol {
	char *name;
	char *uppercase_name;
	struct wl_list interface_list;
	int type_index;
	int null_run_length;
	char *copyright;
	struct description *description;
	bool core_headers;
};

struct interface {
	struct location loc;
	char *name;
	char *uppercase_name;
	int version;
	int since;
	struct wl_list request_list;
	struct wl_list event_list;
	struct wl_list enumeration_list;
	struct wl_list link;
	struct description *description;
};

struct message {
	struct location loc;
	char *name;
	char *uppercase_name;
	struct wl_list arg_list;
	struct wl_list link;
	int arg_count;
	int new_id_count;
	int type_index;
	int all_null;
	int destructor;
	int since;
	struct description *description;
};

enum arg_type {
	NEW_ID,
	INT,
	UNSIGNED,
	FIXED,
	STRING,
	OBJECT,
	ARRAY,
	FD
};

struct parse_context {
	struct location loc;
	XML_Parser parser;
	struct protocol *protocol;
	struct interface *interface;
	struct message *message;
	struct enumeration *enumeration;
	struct description *description;
	char character_data[8192];
	unsigned int character_data_length;
};
        包括协议,接口,消息,参数类型,解析上下文,着重看下接口的定义,其中包含三个wl_list,分别为xml文件中定义的request,event,enum。request为wayland中client端向server端发送的请求,event为wayland中server端向client端发送的事件,event和request都被定义为一种message,enum为协议中定义的enum值。

        生成两个头文件的函数为emit_header,其中

	printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);

	printf("#ifndef %s_%s_PROTOCOL_H\n"
	       "#define %s_%s_PROTOCOL_H\n"
	       "\n"
	       "#include <stdint.h>\n"
	       "#include <stddef.h>\n"
	       "#include \"%s\"\n\n"
	       "#ifdef  __cplusplus\n"
	       "extern \"C\" {\n"
	       "#endif\n\n",
	       protocol->uppercase_name, s,
	       protocol->uppercase_name, s,
	       g
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值