walyand学习笔记(三) 建立各个数据结构之间的联系

 客户端真正的对象结构体

struct wl_proxy {
struct wl_object object;
struct wl_display *display;
struct wl_event_queue *queue;
uint32_t flags;
int refcount;
void *user_data;
wl_dispatcher_func_t dispatcher;
uint32_t version;
};

Wayland协议里面的那些interface的对象在客户端其实真正的结构体是wl_proxy,而那些结构体都是不存在的,只是一个声明而已,根本不存在。如果读者有看过wayland的源码,会发现一个问题,就是wayland协议里面的那些interface对象,从来都不是程序员自己创建出来的,而是通过wayland的一些接口返回回来的。全部都是,无一例外。读者如果不相信可以自己去找找,并且可以自己尝试创建那些对象,肯定是会报错的,因为那些结构体都是不存在的,创建会编译出错

这 所谓的interface对象是啥呢,看看wayland.xml的描述

<interface name="wl_buffer" version="1">

    <description summary="content for a wl_surface">

      A buffer provides the content for a wl_surface. Buffers are

      created through factory interfaces such as wl_drm, wl_shm or

      similar. It has a width and a height and can be attached to a

      wl_surface, but the mechanism by which a client provides and

      updates the contents is defined by the buffer factory interface.

    </description>

 

    <request name="destroy" type="destructor">

      <description summary="destroy a buffer">

         Destroy a buffer. If and how you need to release the backing

         storage is defined by the buffer factory interface.

 

         For possible side-effects to a surface, see wl_surface.attach.

      </description>

    </request>

 

    <event name="release">

      <description summary="compositor releases buffer">

         Sent when this wl_buffer is no longer used by the compositor.

         The client is now free to reuse or destroy this buffer and its

         backing storage.

 

         If a client receives a release event before the frame callback

         requested in the same wl_surface.commit that attaches this

         wl_buffer to a surface, then the client is immediately free to

         reuse the buffer and its backing storage, and does not need a

         second buffer for the next surface content update. Typically

         this is possible, when the compositor maintains a copy of the

         wl_surface contents, e.g. as a GL texture. This is an important

         optimization for GL(ES) compositors with wl_shm clients.

      </description>

    </event>

</interface>

 一个wl_buffer就是一个Interface对象.

【服务器端的interface对象是在server端创建并返回的】

服务器端真正的对象结构体

struct wl_resource {
struct wl_object object;
wl_resource_destroy_func_t destroy;
struct wl_list link;
struct wl_signal destroy_signal;
struct wl_client *client;
void *data;
};

服务器端所有的interface对象全部都是wl_resource结构体对象.

现在,我们开始通过对结构体之间关系的剖析,逐步把各个零散的概念串联起来

 

 可以看到wl_interface就是贯穿这些结构的核心,也正是wayland.xml中大费周章描述的interface对象。

一个wayland协议xml包含一个或者多个interface, 一个interface里面包含一个或者多个request和event

举个栗子:

<interface name="wl_surface" version="4">
<request name="attach">
<arg name="buffer" type="object" interface="wl_buffer" allow-null="true" summary="buffer of surface contents"/>
<arg name="x" type="int" summary="surface-local x coordinate"/>
<arg name="y" type="int" summary="surface-local y coordinate"/>
</request>
</interface>

 这里wl_surface这个interface对象,有一个名叫attach的方法,这个方法的参数如下:

第一个参数名是buffer, 类型是一个wl_buffer的指针,并且可以为空,其注释为 buffer of surface contents

第二个参数是 int x, 描述是surface-local x coordinate

第三个参数是 int y, 描述是surface-local y coordinate

翻译下来,这个函数大概就是:

void wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y);

第一个参数可以理解为wl_surface的this指针,指出是哪个对象要调用和这个接口。

好了,这里都是xml层面的描述,到了C的层面,这些内容都由wl_message结构体来描述。

其中以signature为相对比较重要,这里还是举个栗子:

以wl_display 的 delete_id为例,它只有一个uint的参数,那么这个结构体就是

{“delete_id”, "u", [NULL]}

NULL意味着uint的参数是一个元对象(primitive), 没有对应的wl_interface

再看一个栗子,比如上面讲到的那个wl_surface的attach方法:

其对应的wl_message结构体就应该是{ “attach”, "4?oii", [&wl_buffer, NULL, NULL] }

后两个NULL的意思是对于后面两个int参数,没有对应的interface对象

好的,到这一步就可以比较深入的了解wayland解析协议文件的输出文件了:

一个协议源文件:里面保存了xml协议文件里面所有的interface转换而成的wl_interface结构体变量,包括wl_message结构体记录的request和event函数。

一个客户端使用的头文件:里面封装了wl_proxy转换成指定interface假声明的结构体操作的接口函数,以及request函数的实现,但是这个request只是把请求发送到服务器端,实际调用是在服务器端进行。最后,文件里面还封装了一个回调函数的结构体,成员就是所有的event函数指针,需要客户端去实现,并设置到interface的对象里面,该文件生成了这个设置的接口,实际就是填充到wl_object结构体的implementation变量中。


一个服务器端头文件,里面基本和客户端一样的组成。只是结构体是wl_resource,函数结构体的成员是所有request的函数指针。以及所有的event的实现。
也就是说,客户端需要程序员自己实现事件(event),服务器端需要程序员实现请求(request)。

原文地址:https://www.cnblogs.com/Arnold-Zhang/p/15306697.html