go + cgo 和链接

huangapple go评论122阅读模式
英文:

go + cgo and linking

问题

我想将以下C代码作为Go的cgo使用:

  1. #include <X11/extensions/scrnsaver.h>
  2. main() {
  3. XScreenSaverInfo *info = XScreenSaverAllocInfo();
  4. Display *display = XOpenDisplay(0);
  5. XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
  6. printf("%u ms\n", info->idle);
  7. }

使用以下命令进行构建:

  1. gcc -o idle printXIdleTime.c -lX11 -lXss

我为Go的cgo重新编写了该代码:

  1. package tools
  2. // #cgo pkg-config: x11
  3. // #include <X11/extensions/scrnsaver.h>
  4. import "C"
  5. func GetIdleTime() (idleTime uint32) {
  6. var info *C.XScreenSaverInfo
  7. var display *C.Display
  8. info = C.XScreenSaverAllocInfo()
  9. display = C.XOpenDisplay(0)
  10. defaultRootWindow := C.XDefaultRootWindow(display)
  11. C.XScreenSaverQueryInfo(display, defaultRootWindow, info)
  12. idleTime = info.idle
  13. return
  14. }

尝试使用以下命令进行编译:

  1. go build -gccgoflags="-lXss -lX11"

然而,我遇到了链接器错误:

/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

我做错了什么?

英文:

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

  1. #include &lt;X11/extensions/scrnsaver.h&gt;
  2. main() {
  3. XScreenSaverInfo *info = XScreenSaverAllocInfo();
  4. Display *display = XOpenDisplay(0);
  5. XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
  6. printf(&quot;%u ms\n&quot;, info-&gt;idle);
  7. }

build with:

  1. gcc -o idle printXIdleTime.c -lX11 -lXss

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

  1. package tools
  2. // #cgo pkg-config: x11
  3. // #include &lt;X11/extensions/scrnsaver.h&gt;
  4. import &quot;C&quot;
  5. func GetIdleTime() (idleTime uint32) {
  6. var info *C.XScreenSaverInfo
  7. var display *C.Display
  8. info = C.XScreenSaverAllocInfo()
  9. display = C.XOpenDisplay(0)
  10. defaultRootWindow := C.XDefaultRootWindow(display)
  11. C.XScreenSaverQueryInfo(display, defaultRootWindow, info)
  12. idleTime = info.idle
  13. return
  14. }

tried to compile with:

  1. go build -gccgoflags=&quot;-lXss -lX11&quot;

however i'm getting linker errors:

> /tmp/go-build076004816/opensource.stdk/lib/tools/_obj/x11.cgo2.o: In
> function _cgo_c0e279f6f16e_Cfunc_XScreenSaverAllocInfo&#39;: ./x11.go:52:
&gt; undefined reference to
XScreenSaverAllocInfo'
> /tmp/go-build076004816/opensource.stdk/lib/tools/_obj/x11.cgo2.o: In
> function _cgo_c0e279f6f16e_Cfunc_XScreenSaverQueryInfo&#39;: ./x11.go:65:
&gt; undefined reference to
XScreenSaverQueryInfo' collect2: error: ld
> returned 1 exit status

what am i doing wrong?

答案1

得分: 5

这是我构建它的方式。请注意#cgo LDFLAGS行,这可能是你所缺少的。我还必须进行一些其他更改才能构建它。在我的Linux机器上,它似乎返回了正确的答案!

  1. package tools
  2. // #cgo LDFLAGS: -lXss -lX11
  3. // #include <X11/extensions/scrnsaver.h>
  4. import "C"
  5. func GetIdleTime() (idleTime uint32) {
  6. var info *C.XScreenSaverInfo
  7. var display *C.Display
  8. info = C.XScreenSaverAllocInfo()
  9. display = C.XOpenDisplay(nil)
  10. defaultRootWindow := C.XDefaultRootWindow(display)
  11. C.XScreenSaverQueryInfo(display, C.Drawable(defaultRootWindow), info)
  12. idleTime = uint32(info.idle)
  13. return
  14. }
英文:

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!

  1. package tools
  2. // #cgo LDFLAGS: -lXss -lX11
  3. // #include &lt;X11/extensions/scrnsaver.h&gt;
  4. import &quot;C&quot;
  5. func GetIdleTime() (idleTime uint32) {
  6. var info *C.XScreenSaverInfo
  7. var display *C.Display
  8. info = C.XScreenSaverAllocInfo()
  9. display = C.XOpenDisplay(nil)
  10. defaultRootWindow := C.XDefaultRootWindow(display)
  11. C.XScreenSaverQueryInfo(display, C.Drawable(defaultRootWindow), info)
  12. idleTime = uint32(info.idle)
  13. return
  14. }

答案2

得分: 2

请注意,这可以通过本地的X Go Binding和ScreenSaver扩展来完成:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "github.com/BurntSushi/xgb"
  6. "github.com/BurntSushi/xgb/xproto"
  7. "github.com/BurntSushi/xgb/screensaver"
  8. )
  9. func main() {
  10. X, err := xgb.NewConn()
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. if err = screensaver.Init(X); err != nil {
  15. log.Fatal(err)
  16. }
  17. root := xproto.Setup(X).DefaultScreen(X).Root
  18. info, err := screensaver.QueryInfo(X, xproto.Drawable(root)).Reply()
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. fmt.Printf("Idle: %d\n", info.MsSinceUserInput)
  23. }

输出:

  1. [andrew@Liger go] go run xscreensaver_idle.go
  2. Idle: 1040
英文:

Note that this can be done with the native X Go Binding and the ScreenSaver extension:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;log&quot;
  5. &quot;github.com/BurntSushi/xgb&quot;
  6. &quot;github.com/BurntSushi/xgb/xproto&quot;
  7. &quot;github.com/BurntSushi/xgb/screensaver&quot;
  8. )
  9. func main() {
  10. X, err := xgb.NewConn()
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. if err = screensaver.Init(X); err != nil {
  15. log.Fatal(err)
  16. }
  17. root := xproto.Setup(X).DefaultScreen(X).Root
  18. info, err := screensaver.QueryInfo(X, xproto.Drawable(root)).Reply()
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. fmt.Printf(&quot;Idle: %d\n&quot;, info.MsSinceUserInput)
  23. }

Outputs:

  1. [andrew@Liger go] go run xscreensaver_idle.go
  2. Idle: 1040

huangapple
  • 本文由 发表于 2013年2月13日 06:24:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/14842980.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定