如何为 DBus 服务器制作一个最小的工作示例?

问题描述 投票:0回答:1

DBus
的文档中有这个例子,

ping :: MethodCall -> IO Reply
ping _ = ReplyReturn []

sayHello :: String -> IO String
sayHello name = return ("Hello " ++ name ++ "!")

 export client "/hello_world"
   defaultInterface { interfaceName = "com.example.HelloWorld"
                    , interfaceMethods =
                      [ method "com.example.HelloWorld" "Ping" ping
                      , autoMethod "com.example.HelloWorld" "Hello" sayHello
                      ]
                    }

这应该可以帮助我了解如何实现基于 dbus 的服务器

但是,该示例在几个方面似乎有点过时:

  • 我在该文档中找不到
    method
    (有相关的
    Method
    makeMethod
    autoMethod
    );
  • 通过查看这些,我认为
    ping
    也有一个过时的签名,也许它应该返回
    DBusR Reply
    而不是
    IO Reply
  • autoMethod
    给出了 3 个参数,但应该给出 2 个参数,只需删除
    "Hello"
    就可以进行类型检查,但是...我读过
    AutoMethod
    的文档,但我不太明白.

但最重要的是这个例子不完整。我该如何使用它?

export
的文档为

在给定的

Interface
处导出给定的
ObjectPath

让我觉得我所要做的就是将片段的最后一部分(对

export
的调用)放入
main :: IO ()
函数中,然后使用
_ <- getChar
return ()
之前的其他内容使其保持活动状态,但是我仍然不知道如何...调用这些函数
sayHello
ping
。看着这个答案我有点觉得我应该使用
dbus-send
,但是无论我如何根据上面的代码片段编译Haskell废话,如果我运行

dbus-send --session --print-reply --dest="com.example.HelloWorld" /hello_world com.example.HelloWorld.Ping

我明白了

Error org.freedesktop.DBus.Error.ServiceUnknown: The name is not activatable

根据我目前的知识,这可能是因为我应该做一些与 Haskell 无关的设置,以及因为我写了 Haskell 废话。


无论如何,这是我设法编译的一些代码,但实际上并没有做任何事情:

{-# LANGUAGE OverloadedStrings #-}

import DBus
import DBus.Client

ping :: MethodCall -> IO Reply
ping _ = return (ReplyReturn [])

sayHello :: String -> IO String
sayHello name = return ("Hello " ++ name ++ "!")

main :: IO ()
main = do
    client <- connectSession

    export client "/hello_world"
        defaultInterface { interfaceName = "com.example.HelloWorld"
                         , interfaceMethods =
                           [
                           autoMethod "com.example.HelloWorld" sayHello
                           ]
                         }
    _ <- getLine
    return ()
haskell server functional-programming dbus
1个回答
0
投票

错误消息谈论的是总线名称,基本上是总线上每个服务(甚至每个客户端)的“地址”。最重要的是,这意味着所请求的

--dest=
姓名当前不存在在公交车上。

(除此之外,该错误消息还意味着 dbus-daemon 不知道如何按需启动您的服务,但您可以安全地忽略它 - “激活”只是自动启动机制,当您'重新手动启动您的服务。)

总线名称不是通过配置设置的(仅用于自动启动);每次启动并连接到总线时,服务都会使用特殊的总线调用“认领”它们。您的流程需要调用

requestName
(docs) 才能实现这一点。

接口名称不是——接口只是您自己的代码用来分组或区分方法的东西,而服务名称(又名总线名称,又名唯一名称)是整个过程的实际“D-Bus 地址” 。对于简单的 1 对象、1 接口服务,它们很可能是相同的,但如果您浏览

d-spy
,您会看到许多示例,其中一个服务使许多对象可用,并且具有多个接口,所有这些都在单个总线名称。

理想情况下,应该在设置并导出初始对象之后声明总线名称,以防止对服务的调用失败并出现“没有此类对象”或类似的情况,因为它碰巧到达得太早了。

© www.soinside.com 2019 - 2024. All rights reserved.