You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写可运行的Haskell DBus服务器最小示例?

修复Haskell DBus服务器最小示例问题

核心错误原因

你遇到的ServiceUnknown错误,本质是没有向DBus注册服务名。export仅导出了对象路径和接口,但DBus不知道com.example.HelloWorld这个服务名对应你的进程,必须显式调用requestName完成注册。

过时API修正与完整可运行代码

针对文档示例的过时问题,结合dbus-1.3.2的实际API,修正后的完整代码如下:

{-# LANGUAGE OverloadedStrings #-}

import DBus
import DBus.Client
import DBus.Internal.Types (MethodCall)
import Control.Monad.IO.Class (liftIO)

-- Ping方法:无参数,返回空回复
-- 签名改为MethodCall -> DBusR Reply,使用DBusR monad处理DBus上下文
ping :: MethodCall -> DBusR Reply
ping _ = return $ ReplyReturn []

-- Hello方法:接收String,返回String
sayHello :: String -> DBusR String
sayHello name = return $ "Hello " ++ name ++ "!"

main :: IO ()
main = do
    -- 连接到session总线
    client <- connectSession

    -- 注册DBus服务名,这是解决ServiceUnknown的关键步骤
    _ <- requestName client "com.example.HelloWorld" []

    -- 导出对象路径与接口
    export client "/hello_world" $ defaultInterface
        { interfaceName = "com.example.HelloWorld"
        , interfaceMethods =
            [ -- 使用makeMethod创建Ping方法:指定接口名、方法名、处理函数
              makeMethod "com.example.HelloWorld" "Ping" ping
              -- 使用autoMethod创建Hello方法:指定接口名,自动推导方法名和参数/返回类型
            , autoMethod "com.example.HelloWorld" sayHello
            ]
        }

    putStrLn "DBus server running. Press Enter to exit."
    _ <- getLine
    return ()

关键API说明

  • makeMethod替代过时的method:
    签名为makeMethod :: InterfaceName -> MemberName -> (MethodCall -> DBusR Reply) -> Method,用于手动定义方法,需要指定接口名、方法名,以及处理MethodCall的函数(返回DBusR Reply而非旧示例的IO Reply)。

  • autoMethod的正确用法:
    签名为autoMethod :: AutoMethod a => InterfaceName -> a -> Method,它会自动推导方法名(从传入的函数名)、参数类型和返回类型,无需手动指定方法名。如果需要自定义方法名(比如想叫Hello而非sayHello),可以用autoMethodWithName显式指定:

    autoMethodWithName "com.example.HelloWorld" "Hello" sayHello
    
  • requestName的必要性:
    必须调用此函数向DBus注册服务名,否则外部工具(如dbus-send)无法找到你的服务。

测试方法

编译运行代码后,在终端执行以下命令测试:

测试Ping方法

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

会返回空的回复(符合Ping方法的定义)。

测试Hello方法

dbus-send --session --print-reply --dest="com.example.HelloWorld" /hello_world com.example.HelloWorld.sayHello string:"Alice"

会返回string "Hello Alice!"。如果用自定义方法名Hello,则命令改为:

dbus-send --session --print-reply --dest="com.example.HelloWorld" /hello_world com.example.HelloWorld.Hello string:"Alice"

内容的提问来源于stack exchange,提问作者Enlico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:27:15