CGO将Xlib XEvent结构转换为字节数组?

时间:2015-06-14 22:28:47

标签: c go xlib cgo

我正在Golang中创建一个简单的窗口管理器(基于tinywm中c代码的代码)。要使用Xlib,我使用的是cgo,所以我的标题是:

// #cgo LDFLAGS: -lX11
// #include <X11/Xlib.h>

我有一个变量声明,例如:

event := C.XEvent{}

然后,我使用它来分配给它,稍后,在事件循环中:

C.XNextEvent(display, &event) // Yes, display is defined

但是当我尝试访问事件的属性时,例如xbutton或xkey,我收到错误:

event.xbutton undefined (type C.XEvent has no field or method xbutton)

当我查看XEvent的cgo输出时,它看起来像这样,在_cgo_gotypes.go文件中:

type _Ctype_XEvent [192] byte

我无法弄清楚发生了什么,虽然我预感到类型[192] byte对于C结构类型是非常错误的。如果这有帮助,XEvent结构在C库中看起来像这样:

typedef union _XEvent {

    int type;   /* must not be changed */
    XAnyEvent xany;
    XKeyEvent xkey;
    XButtonEvent xbutton;
    XMotionEvent xmotion;
    XCrossingEvent xcrossing;
    XFocusChangeEvent xfocus;
    XExposeEvent xexpose;
    XGraphicsExposeEvent xgraphicsexpose;
    XNoExposeEvent xnoexpose;
    XVisibilityEvent xvisibility;
    XCreateWindowEvent xcreatewindow;
    XDestroyWindowEvent xdestroywindow;
    XUnmapEvent xunmap;
    XMapEvent xmap;
    XMapRequestEvent xmaprequest;
    XReparentEvent xreparent;
    XConfigureEvent xconfigure;
    XGravityEvent xgravity;
    XResizeRequestEvent xresizerequest;
    XConfigureRequestEvent xconfigurerequest;
    XCirculateEvent xcirculate;
    XCirculateRequestEvent xcirculaterequest;
    XPropertyEvent xproperty;
    XSelectionClearEvent xselectionclear;
    XSelectionRequestEvent xselectionrequest;
    XSelectionEvent xselection;
    XColormapEvent xcolormap;
    XClientMessageEvent xclient;
    XMappingEvent xmapping;
    XErrorEvent xerror;
    XKeymapEvent xkeymap;
    long pad[24];
} XEvent;

1 个答案:

答案 0 :(得分:0)

如上所述in the cgo documentation

  

由于Go在一般情况下不支持C的联合类型,因此C的联合类型表示为具有相同长度的Go字节数组。

另一个问题:Golang CGo: converting union field to Go type
a go-nuts mailing list post可能会有进一步的帮助。

简而言之,您将无法简单地使用或简单地与使用联合的C代码进行交互。至少你需要设置类似unsafe.Pointer的东西来手动操作字段/类型,你的例子看起来像一个特别讨厌的情况(即它不仅仅是几个不同类型的整数的联合,如上面链接的情况是)。

鉴于名称,我得到的印象是您可能希望在Go中创建一个“事件”界面,并将每个必需的事件类型实现为实现该界面的Go类型。然后根据Go“union”/ [] byte的第一个C.sizeof(int)字节编写转换为C union的代码(在Go或C中)(我认为第一个int type字段很可能如果X ...事件类型包含在每个中。