概览
像D-Bus包一样,LibOSSO的基本功能是执行远程过程调用(RPC)。因为RPC将调用进入其它进程并因此消耗时间,LibOSSO提供两种不同调用机制:同步和异步调用,给不同的编程需要。什么是RPC、两种RPC和正常进入进程程序调用的区别,将是此文主题,并在Moblin SDK中介绍。
调用RPC前,调用者(客户端应用程序)需要知道服务(其它进程)的名称提供给函数调用,将提供函数调用、函数名称、找到该函数的路径和参数给调用者。该信息通常通过D-Bus服务进程发布,实现通信服务调用通过文档或XML页。阅读D-Bus文档获得更多细节。D-Bus实现命名机制给地址远程过程。
这是一个例子:
//
// Definition of sample DBUS service known name,
// object path, interface name and method call name
//
#define SAMPLE_SERVICE_NAME "org.freedesktop.Notifications"
#define SAMPLE_SERVICE_OPATH "/org/freedesktop/Notifications"
#define SAMPLE_SERVICE_IFACE "org.freedesktop.Notifications"
#define SAMPLE_SERVICE_METHOD "GetServerInformation"
远程调用的“address”有4个部分:全局服务名称,执行远程过程的对象路径,接口名称,函数(过程)名称。地址远程过程需要这四个组件。在我们的样例代码中,我们使用“GetServerInformation”过程在通告服务,该服务由http://freedesktop.org提供。查阅D-Bus documentation可获得地址机制细节。
使用LibOSSO的同步RPC
顾名思义,LibOSSO的同步RPC将屏蔽执行的调用线程直到调用返回、超时或错误发生。但是同步RPC耗费时间,所以它应该谨慎使用,避免无响应。
简单的发出同步PRC:调用“osso_rpc_run”函数将开始执行。在此函数中,调用者需要通过4部分过程调用地址,加上参数,用该过程调用自身。下面是例子:
//
// Code to illustrate how to make synchronous RPC call through libosso
//
result = osso_rpc_run (
osso_context, // OSSO context returned by osso_initialize
SERVICE_NAME, // Well-known service name
SERVICE_OPATH, // Object path
SERVICE_IFACE, // Interface
FUNCTION_NAME, // The function name to call into
&methodResult, // function return value
// Below are the arguments for the RPC.
DBUS_TYPE_STRING, string_arg_sample, // A sample str argument
DBUS_TYPE_UINT32, uint_arg_sample, // A sample int argument
DBUS_TYPE_INVALID // The arg temination tag
);
if (result != OSSO_OK)
{
g_error("failed to exec 'osso_rpc_run!/n");
return;
}
提示:如果该过程调用将返回多个值(在D-Bus中是可能的),LibOSSO目前不能提供这样的机制,但是会返回第一个值。
与libdbus相比,由LibOSSO 提供的“osso_rpc_run”函数非常容易理解与操作。
使用LibOSSO的异步RPC
异步PRC常用于需要花费长时间执行的远程调用。在LibOSSO中,异步RPC通常只需要2个步骤:
1. 执行“rpc_completion_callback”函数,原型定义在LibOSSO文件。顾名思义,一旦RPC返回请求,此函数将被调用。
2. 调用“osso_rpc_async_run”函数提交一个异步RPC请求。
在提交RPC请求后,函数“osso_rpc_async_run”将立即返回。函数下面的代码不会判断调用RPC执行与否,RPC完成信号应该掌握在回调中。下列伪代码演示执行异步RPC的步骤。
//
// Code to illustruate LibOSSO asynchronous RPC.
//
result = osso_rpc_async_run (
osso_context, // OSSO context returned by osso_initialize
SERVICE_NAME, // Well-known service name
SERVICE_OPATH, // Object path
SERVICE_IFACE, // Interface
FUNCTION_NAME, // The function name to call into
rpc_completion_cb, // Function pointer of completion callback
(gpointer)usr_data,// The user data pointer passed to callback
// Below are the arguments for the RPC.
DBUS_TYPE_STRING, string_arg_sample, // A sample str argument
DBUS_TYPE_UINT32, uint_arg_sample, // A sample int argument
DBUS_TYPE_INVALID // The arg temination tag
);
if (result != OSSO_OK)
{
g_error("failed to exec 'osso_rpc_run!/n");
return;
}
……
void rpc_completion_cb (const gchar *interface, const gchar *method,
osso_rpc_t *retval, gpointer data)
{
g_assert (interface != NULL);
g_assert (method != NULL);
g_assert (retval != NULL);
g_assert (data != NULL);
g_print ("Calling async RPC callback 'rpc_completion_cb.../n");
g_print ("interface = %s/n", interface);
g_print ("method = %s/n", method);
//
// Todo: application specific RPC completion logic goes here
//
……
return;
}
注意,可能会在多个不同(且同时发生)的RPC过程调用中使用相同回调函数,因为所有RPC有相同回调原型,回调能根据传递参数识别不同返回。
返回值结构由LibOSSO分配,并将在回调返回时释放,所以无需手动操作[2]。
尝试RPC范例代码
现在我们可参照此文尝试范例代码。转到libosso-sample/rpc目录,输入下面的指令建立范例程序:
$ ./autogen
$ ./configure --prefix=/targets/$MyTarget/fs/usr
$ make
$ make install
注意“$Mytarrget”应被改为由Image Creator 创建Moblin目标系统的真实名称。
切换到目标系统,用下列输入启动同步RPC:
$ libosso-rpc –s
如果所有的准备是正确的,应能看到下列输出:
$ Initialize libosso…
$ Executing "GetServerInformation" RPC method…
$ RPC "GetServerInformation" executed successfully
$ RPC "GetServerInformation" returned: string: "Hildon Desktop Notification Manager"
$ Application quit successfully
输入下列命令测试异步RPC:
$ libosso-rpc –a
如果所有的准备是正确的,应能看到下列输出:
$ Initialize libosso…
$ Executing "GetServerInformation" RPC method…
$ RPC "GetServerInformation" launched successfully
$ Calling async RPC callback "rpc_completion_cb"…
$ interface = org.freedesktop.Notifications
$ method = GetServerInformation
$ RPC "GetServerInformation" returned: string: "Hildon Desktop Notification Manager"
$ Application quit successfully
翻译:徐诚
本文译自Moblin.org技术社区, 点击此处,查看原文