【问题标题】:Errors while using Go with cgo and Xlib将 Go 与 cgo 和 Xlib 一起使用时出错
【发布时间】:2015-12-13 04:03:43
【问题描述】:

我试图在 cgo 的帮助下将 C 代码重写为 Go,但是在尝试运行 go 代码时它给了我一些错误,我不知道如何解决。该代码允许在 Linux 桌面上获取鼠标点击的坐标。

C 代码:

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main () {
    int x=-1, y=-1;
    XEvent event;
    int button;
    Display *display = XOpenDisplay(NULL);
    if (display == NULL) {
    fprintf(stderr, "Cannot connect to X server!\n");
    exit (EXIT_FAILURE);
    }
    Window root= XDefaultRootWindow(display);
    XGrabPointer(display, root, False, ButtonPressMask, GrabModeAsync,
         GrabModeAsync, None, None, CurrentTime);
    while(1){
    XSelectInput(display, root, ButtonReleaseMask);
    while(1) {
      XNextEvent(display,&event);
      switch(event.type) {
    case ButtonPress:
        switch(event.xbutton.button) {
          case Button1:
          x=event.xbutton.x;
          y=event.xbutton.y;
          button=Button1;
          break;

          case Button3:
          x=event.xbutton.x;
          y=event.xbutton.y;
          button=Button3;
          break;
          default:
          break;

        }
        break;
    default:
        break;
      }
      if(x>=0 && y>=0)break;
    }

    if(button==Button1)printf("leftclick at %d %d \n",x,y);
    else printf("rightclick at %d %d \n",x,y);}
    XCloseDisplay(display);
    return 0;
}

转码:

package main

// #cgo LDFLAGS: -lX11
// #include <X11/Xlib.h>
// #include <X11/Xutil.h>
import "C"

import (
    "fmt"
)

func main() {
    var x = -1
    var y = -1
    var event C.XEvent
    var button int
    var display = C.XOpenDisplay(nil)
    if display == nil {
        panic("Cannot connect to X server!\n")
    }

    var root = C.XDefaultRootWindow(display);
    C.XGrabPointer(display, root, C.False, C.ButtonPressMask, C.GrabModeAsync, 
        C.GrabModeAsync, C.None, C.None, C.CurrentTime)
    for {
        C.XSelectInput(display, root, C.ButtonReleaseMask)
        for {
            C.XNextEvent(display, &event)
            switch(C.event.type) {
                case C.ButtonPress:
                    switch C.event.xbutton.button  {
                        case C.Button1:
                            x=C.event.xbutton.x
                            y=C.event.xbutton.y
                            button=C.Button1
                            break

                        case Button3:
                            x=C.event.xbutton.x
                            y=C.event.xbutton.y
                            button=C.Button3
                            break
                            default:
                                break

                    }
                    break
                default:
                    break
            }
            if(x>=0 && y>=0) {
                break
            }
        }
        if(button==Button1) {
            fmt.Printf("leftclick at %d %d \n",x,y)
        }
        else  {
            fmt.Printf("rightclick at %d %d \n",x,y)
        }
    }
    C.XCloseDisplay(display)
}

Go 代码中的错误:

go run g.go
# command-line-arguments
./g.go:29:19: expected selector or type assertion, found 'type'
./g.go:58:3: expected statement, found 'else'
./g.go:63:3: expected '}', found 'EOF'

【问题讨论】:

    标签: go xlib cgo


    【解决方案1】:

    关于“类型”的错误,这是go中的保留字,所以不能直接访问。

    根据this posting,您应该将引用更改为:

    switch C.event._type {
    

    另外,else 不能单独成行。 改成

    if button == Button1 {
        fmt.Printf("leftclick at %d %d \n", x, y)
    } else {
        fmt.Printf("rightclick at %d %d \n", x, y)
    }
    

    switch 语句在 go 中不会落空,因此您的 break 语句是不必要的。

    最后,确保在你的代码上运行 go fmt,你在不需要的地方使用了括号。

    这是一个删除了中断的格式化版本,应该适合你(我没有测试这段代码):

    package main
    
    // #cgo LDFLAGS: -lX11
    // #include <X11/Xlib.h>
    // #include <X11/Xutil.h>
    import "C"
    
    import (
        "fmt"
    )
    
    func main() {
        var x = -1
        var y = -1
        var event C.XEvent
        var button int
        var display = C.XOpenDisplay(nil)
        if display == nil {
            panic("Cannot connect to X server!\n")
        }
    
        var root = C.XDefaultRootWindow(display)
        C.XGrabPointer(display, root, C.False, C.ButtonPressMask, C.GrabModeAsync,
            C.GrabModeAsync, C.None, C.None, C.CurrentTime)
        for {
            C.XSelectInput(display, root, C.ButtonReleaseMask)
            for {
                C.XNextEvent(display, &event)
                switch C.event._type {
                case C.ButtonPress:
                    switch C.event.xbutton.button {
                    case C.Button1:
                        x = C.event.xbutton.x
                        y = C.event.xbutton.y
                        button = C.Button1
    
                    case Button3:
                        x = C.event.xbutton.x
                        y = C.event.xbutton.y
                        button = C.Button3
                    }
                }
                if x >= 0 && y >= 0 {
                    break
                }
            }
            if button == Button1 {
                fmt.Printf("leftclick at %d %d \n", x, y)
            } else {
                fmt.Printf("rightclick at %d %d \n", x, y)
            }
        }
        C.XCloseDisplay(display)
    }
    

    【讨论】:

    • 谢谢,有用,但是:go run g2.go # command-line-arguments could not determine kind of name for C.event
    • ...所以,这里有一个冲突:如何声明类似 C.event.xbutton.x 的东西并使用类似 C.event.xbutton.x 的东西
    • 在这种情况下,它是 event.xbutton.x,而不是 C.event.xbutton.x,C 前缀仅在声明类型或调用函数时使用。由于您已经有一个事件变量,只需直接访问这些字段
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 2017-11-13
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多