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 to
XScreenSaverAllocInfo' /tmp/go-build076004816/opensource.stdk/lib/tools/_obj/x11.cgo2.o: In function_cgo_c0e279f6f16e_Cfunc_XScreenSaverQueryInfo': ./x11.go:65: undefined reference to
XScreenSaverQueryInfo' collect2: error: ld returned 1 exit status
what am i doing wrong?
Well, Go code is statically linked, but the runtime may try to dynamically load libc for DNS resolving. Use of cgo of course drastically change everything. By default, nowadays the toolchain also supports generating dynamic libraries.
The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling. You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it.
Go allows linking against C libraries or pasting in in-line code.
Cgo lets Go packages call C code. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With