Search code examples
linkergocgo

go + cgo and linking


i want to use the following c as Go's cgo:

#include <X11/extensions/scrnsaver.h>

main() {
  XScreenSaverInfo *info = XScreenSaverAllocInfo();
  Display *display = XOpenDisplay(0);

  XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
  printf("%u ms\n", info->idle);
}

build with:

gcc -o idle printXIdleTime.c -lX11 -lXss

i re-wrote that code for Go's cgo:

package tools

// #cgo pkg-config: x11
// #include <X11/extensions/scrnsaver.h>
import "C"

func GetIdleTime() (idleTime uint32) {
    var info *C.XScreenSaverInfo
    var display *C.Display 

    info = C.XScreenSaverAllocInfo()
    display = C.XOpenDisplay(0)

    defaultRootWindow := C.XDefaultRootWindow(display)

    C.XScreenSaverQueryInfo(display, defaultRootWindow, info)
    idleTime = info.idle

    return
}

tried to compile with:

go build -gccgoflags="-lXss -lX11"

however i'm getting linker errors:

/tmp/go-build076004816/opensource.stdk/lib/tools/_obj/x11.cgo2.o: In function _cgo_c0e279f6f16e_Cfunc_XScreenSaverAllocInfo': ./x11.go:52: undefined reference toXScreenSaverAllocInfo' /tmp/go-build076004816/opensource.stdk/lib/tools/_obj/x11.cgo2.o: In function _cgo_c0e279f6f16e_Cfunc_XScreenSaverQueryInfo': ./x11.go:65: undefined reference toXScreenSaverQueryInfo' collect2: error: ld returned 1 exit status

what am i doing wrong?


Solution

  • This is how I got it to build. Note the #cgo LDFLAGS line which is probably what you are missing. I had to make a few other changes to make it build. It seems to be returning the right answer on my Linux machine!

    package tools
    
    // #cgo LDFLAGS: -lXss -lX11
    // #include <X11/extensions/scrnsaver.h>
    import "C"
    
    func GetIdleTime() (idleTime uint32) {
        var info *C.XScreenSaverInfo
        var display *C.Display
    
        info = C.XScreenSaverAllocInfo()
        display = C.XOpenDisplay(nil)
    
        defaultRootWindow := C.XDefaultRootWindow(display)
    
        C.XScreenSaverQueryInfo(display, C.Drawable(defaultRootWindow), info)
        idleTime = uint32(info.idle)
    
        return
    }