首页 > 解决方案 > golang dbus 服务器示例

问题描述

Golang dbus 模块提供了以下示例,但不清楚服务器如何接收消息并响应。一个 ping/pong 示例表示赞赏:

package main

import (
    "fmt"
    "os"

    "github.com/godbus/dbus"
    "github.com/godbus/dbus/introspect"
)

const intro = `
<node>
    <interface name="com.github.guelfey.Demo">
        <method name="Foo">
            <arg direction="out" type="s"/>
        </method>
    </interface>` + introspect.IntrospectDataString + `</node> `

type foo string

func (f foo) Foo() (string, *dbus.Error) {
    fmt.Println(f)
    return string(f), nil
}

func main() {
    conn, err := dbus.ConnectSessionBus()
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    f := foo("Bar!")
    conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
    conn.Export(introspect.Introspectable(intro), "/com/github/guelfey/Demo",
        "org.freedesktop.DBus.Introspectable")

    reply, err := conn.RequestName("com.github.guelfey.Demo",
        dbus.NameFlagDoNotQueue)
    if err != nil {
        panic(err)
    }
    if reply != dbus.RequestNameReplyPrimaryOwner {
        fmt.Fprintln(os.Stderr, "name already taken")
        os.Exit(1)
    }
    fmt.Println("Listening on com.github.guelfey.Demo / /com/github/guelfey/Demo ...")
    select {}
}

标签: goserverdbus

解决方案


(这只是我阅读程序和文档的印象。您自己测试一下,看看这是否准确)

https://pkg.go.dev/github.com/godbus/dbus#Conn.Export

func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error

如果接收到对给定路径和接口的方法调用,如果参数匹配并且最后返回值的类型为 *Error,则以 v 作为接收者调用具有相同名称的导出方法。如果此 *Error 不为零,则将其作为错误发送回调用者。否则,将使用其他返回值作为其主体发送方法回复。

程序将f类型传递fooconn.Export.

foo具有与描述的模式匹配的此方法:

func (f foo) Foo() (string, *dbus.Error)

响应是此函数的返回值,不包括最终错误,即string(f). ("Bar!"在这种情况下)。

最后空的 select 语句select {}是我以前从未见过的巧妙技巧。它只是一个永远阻塞的语句。您可以在这个问题中阅读更多相关信息。它在这里只是用来阻止maingoroutine 终止。在 Go 中,当主 goroutine 完成时,整个过程将立即结束。

鉴于这个空选择是一个“聪明的把戏”,最好用一个简单的注释来解释它:

// Blocks forever
select {}

可能这个例子让人困惑的原因是因为这个Export方法非常神奇。它采用一个名称模糊的空接口值,并根据可能使用反射的一些内部过程来计算如何处理它。除非您阅读该函数的文档,否则很难猜出它会做什么。


推荐阅读