×
Namespaces

Variants
Actions
(Difference between revisions)

Qt Service Framework 文档

From Nokia Developer Wiki
Jump to: navigation, search
flycarl (Talk | contribs)
flycarl (Talk | contribs)
Line 67: Line 67:
 
service管理器对象的当前作用域决定了 接口默认的指配是对所有用户有效还是只对当前用户有效。 用户作用域没有定义时讲使用系统默认。这使得用户可以自定义个人参数。当一个新的接口第一次安装服务时,默认设置为 system wide default selection。
 
service管理器对象的当前作用域决定了 接口默认的指配是对所有用户有效还是只对当前用户有效。 用户作用域没有定义时讲使用系统默认。这使得用户可以自定义个人参数。当一个新的接口第一次安装服务时,默认设置为 system wide default selection。
  
====基于QObject的service====
+
====基于QObject的服务====
 
这是最常见的与servicer交互的方法。
 
这是最常见的与servicer交互的方法。
  
Line 75: Line 75:
 
     QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt"));
 
     QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt"));
 
</code>
 
</code>
The above invocation of the file storage object's deleteFile() function is done via the service's QMetaObject. The client does not require any knowledge of the objects actual type and therefore does not have to link against a service specific library.
+
上面的代码通过service的[http://qt.nokia.com/doc/4.7/qmetaobject.html QMetaObject]调用文件存储对象的deleteFile() 方法。客户端不需要知道对象的类型,因此也没有链接到具体的service库。
Typed services
+
  
So far all lookup mechanism returned a QObject pointer. This pointer can be utilized by introspecting the object, using Qt's meta object system. However in some use cases it may be more convenient to directly interact with the service object by including the service header and/or linking against the service provider. The main advantage is compile time checking. Its disadvantage is that client and service must share the implementation of the service object via a library they link against or via a common header file. Note that such sharing breaks the fundamental ServiceFramework principle of separating clients from service as changes of the service type may require changes to both, services and clients.
+
====使用某种具体类型的服务====
 +
之前的查找机制都返回一个QObject指针。这个指针可以利用Qt的meta object系统来内省(introspect)对象。 当然在某些情况下,直接使用service对象更方便些,直接引用service的头文件,链接service提供方。这样做主要的好处是编译期检查。 缺点是客户端和service必须共享service对象的实现,链接库或者共享头文件。这样做违背了 服务框架(Service Framework )的设计原则,原意是分离客户端和服务,这样做之后两者就产生了关联,改变服务类型,需要同时改变服务和客户端。
  
The subsequent code snippet demonstrates how this may look like:
+
下面的代码片段演示了大概的实现:
  
 +
<code cpp>
 
  #include <filestorage.h>
 
  #include <filestorage.h>
 
  ...
 
  ...
Line 90: Line 91:
 
  if (storage)
 
  if (storage)
 
     storage->deleteFile("/tmp/readme.txt");
 
     storage->deleteFile("/tmp/readme.txt");
 +
</code>
 +
=='''服务作用域'''==
 +
'''QServiceManager '''在用户作用域或系统作用域中操作。默认在用户作用域。作用域的选择决定服务是对全局有效或只是对当前的用户有效, 查找服务和接口时是在全局服务集合中查找,还是全局服务并上当前用户的服务集合中查找。
 +
 +
==='''用户作用域'''===
 +
在用户作用域, 服务注册在当前用户注册的存储点。当使用setInterfaceDefault()设置一个接口的默认服务时,服务可以是用户特有的或全局的服务。
 +
 +
查找服务和接口时,管理器会优先搜索用户特有的服务,没有找到时,在用户有权限时再查找全局的服务。
 +
 +
 +
在服务被添加,删除时放送信号[http://doc.qt.nokia.com/qtmobility-1.1.0/qservicemanager.html#serviceAdded QServiceManager::serviceAdded()] 和[http://doc.qt.nokia.com/qtmobility-1.1.0/qservicemanager.html#serviceRemoved QServiceManager::serviceRemoved()]。这些信号可以指定作用域参数。(只有当用户有足够的权限时才会得到全局服务的增减信号)
 +
 +
==='''系统作用域'''===
 +
 +
在系统作用域,服务注册在全局存储点。管理器不访问用户特定的操作。服务和接口在全局服务中找不到就返回fail。服务只注册在全局存储点,如果使用setInterfaceDefault()注册一个用户特定的服务,则返回fail。
 +
QServiceManager::serviceAdded() 和QServiceManager::serviceRemoved()只发送全局服务的增减信号。
 +
 +
----
 +
=='''增加,移除服务’''==
 +
 +
服务可以在运行期安装和移除。用一个XML文件来描述服务的meta data,通过meta data的描述来链接服务的代码。
 +
 +
==='''XML格式'''===
 +
使用XML描述的 meta data和服务的位置来安装服务,XML文件的文件类型定义如下:
 +
<code>
 +
<!ELEMENT SFW ( service ) >
 +
<!ATTLIST SFW version (1.0|1.1) #REQUIRED >
 +
<!ELEMENT service ( name, filepath | ipcaddress, description?, interface+ ) >
 +
<!ELEMENT description ( #CDATA ) >
 +
<!ELEMENT filepath ( #PCDATA ) >
 +
<!ELEMENT ipcaddress ( #PCDATA ) >
 +
<!ELEMENT interface ( name, version, description?, capabilities?, customproperty* ) >
 +
<!ELEMENT capabilities ( #PCDATA ) >
 +
<!ELEMENT name ( #PCDATA ) >
 +
<!ELEMENT version ( #PCDATA ) >
 +
<!ELEMENT customproperty ( #CDATA ) >
 +
<!ATTLIST customproperty key NMTOKEN #REQUIRED >
 +
</code>
 +
 +
元素和属性的意义如下:
 +
{|
 +
|'''Element''' |'''SubElement'''  |'''Description'''
 +
|-
 +
|SFW| |
 +
 +
 +
 +
 +
|The service framework XML version tag that encapsulates the service XML. Must provide the version attribute that follows the major.minor notation and must equate to supported Qt Service Framework versions. This means the minimum version is 1.0 however users are recommended to always specify the highest available version.
 +
|-
 +
|service
 +
 +
|
 +
 +
 +
|The service tag can contain an arbitrary number of interface tags and one description tag.
 +
 +
|-
 +
|"
 +
 +
 +
|description
 +
 +
 +
|A user readable description of the purpose of the service.
 +
|-
 +
|"
 +
 +
 +
|filepath
 +
 +
 +
|The absolute path and name of the plug-in to be loaded when this service is requested. Alternatively if the plug-in name only is provided the standard library paths (see QCoreApplication::libraryPaths()) are used to find the plug-in. Note that if the plugin name is given only, platform specific parts such as the suffix ".dll" and ".so" or plugin prefix "lib" should be removed to enable cross platform resolution. QLibrary is used to determine the platform specific parts of the plugin.
 +
|-
 +
|"
 +
 +
|
 +
|ipcaddress
 +
|
 +
 +
|The socket name or path that the inter-process service will be published on that will provide clients with remote access. Should be the same name as the executable for the service without any suffix such as ".exe" etc.
 +
|-
 +
|"
 +
 +
 +
|name
 +
 +
 +
|The name of the service.
 +
|-
 +
|interface
 +
 +
 +
|
 +
 +
|The interface describes the properties of the interface.
 +
|-
 +
|"
 +
 +
 +
|capabilities
 +
 +
 +
|This property is a list of arbitrary strings which are interpreted as permissions/capabilities. The list elements are comma-separated and spaces after commas are not permitted. This list can be empty.
 +
|-
 +
|"
 +
 +
 +
|name
 +
 +
 +
|The name of the interface using the Java class name notation. (e.g. com.nokia.qt.TestService)
 +
|-
 +
|"
 +
 +
 +
|version
 +
 +
 +
|This property contains the interface and implementation version. The version tag follows the major.minor notation. The major version indicates the interface version the minor version the implementation version.
 +
 +
The version number must be greater than 1.0. The version cannot be less than 1.0 because the Service Framework is dependent on the fact that services must be binary compatible between major versions, and services with versions less than 1.0 are unlikely to be binary compatible with later versions.
 +
|-
 +
|"
 +
 +
 +
|description
 +
 +
 +
|A user readable description of the purpose of the interface.
 +
|-
 +
|"
 +
 +
 +
|customproperty
 +
 +
 +
|An implementation specific key value pair which can be used for filtering or as description.
 +
|}
 
==<u>相关链接</u>==
 
==<u>相关链接</u>==
 
*[[Qt Mobility 开发]]
 
*[[Qt Mobility 开发]]

Revision as of 12:15, 9 January 2011

Contents

Qt Service Framework

Qt服务框架(Qt Service Framework )使客户端可以发现和实例化任意服务(service)。



命名空间

QtMobility API 放在 QtMobility 的命名空间. 这是为以后Mobility APIs 集成到 Qt做准备. 参考Quickstart guide中的例子体会这个命名空间如何影响使用QtMobility的开发development.


简介

Qt Service Framework 定义了统一的方法 在不同的平台间查找,实现和访问各种service。

利用 服务接口(service interface),版本号(version),基于QObject的内省(introspection)这3个信息,可以兼容和访问多个平台的某个service, 使得通过Qt的客户端可以不依赖平台的调用服务,实现跨进程的通信(IPC)。


概览

一个service是一个独立的组件提供给客户端(client)定义好的操作。客户端可以通过service的名称,版本号和service对象提供的接口来查找服务。 查找到service后,框架启动service并返回一个指针。QServiceManager 是做这些事情的主要接口,客户端通过QserviceManager来访问service。service也可以像一个客户端一样向service framework查询安装在系统上的其他service。

服务提供者通过插件(plug-ins)来实现。QServicePluginInterface是plug-in的主要接口。为了避免客户端依赖某个具体的库,服务必须继承自QObject。这样QMetaObject 系统可以用来动态的发现和唤醒服务的能力。要使QmetaObject机制充分的工作,service必须满足,其所有的方法都是通过 signal,slot,property 或invokable function来实现(参阅Q_INVOKABLE宏的定义)

每个service plug-in 只实现一个service,但是可以为多个接口提供多个实现。这样 service (plug-in)具有一定的后向兼容性,即使 当你需要使用一个新的接口名而破坏了主要的接口服务的兼容性,已有的客户端可以继续使用之前的服务接口,新的客户端可以利用新的接口。

service可以接受远程进程。在service管理器上注册后 进程通过signal,slot,invokable function和property来通信,就像本地对象一样。service可以设定为在客户端间共享,或针对一个客户端。


如何使用框架

这一章假设用户想访问文件存储服务(FileStorage service),这个服务提供了com.nokia.qt.examples.FileStorage接口的一个实现。service framework提供了访问这些实现的多种方法。

QServiceManager service管理器是查找和实例化service的主要类。可以通过指定service的meta data 来查找service,也可以通过默认的查找机制来查找service。

冗余查找(Verbose)

客户端代码知道service及其接口的详细信息时,可用如下代码找到service

 QServiceManager manager;
QServiceFilter filter("com.nokia.qt.examples.FileStorage");
filter.setServiceName("FileStorage");
 
// find services complying with filter
QList<QServiceInterfaceDescriptor> foundServices;
foundServices = manager.findInterfaces(filter);
Q_ASSERT(foundServices.count());
 
// instantiate the FileStorage object
QObject *fileStorage;
fileStorage = manager.loadInterface(foundServices.at(0));

默认查找

假设客户端知道用哪个接口,但是并不关心实现接口的服务是哪种类型,哪种版本。 这时可使用默认查找机制来创建service对象的实例。

 QServiceManager manager;
manager.setInterfaceDefault("FileStorageService", "com.nokia.qt.examples.FileStorage");

上面的代码 QServiceManager::setInterfaceDefault() 把FileStorageService 注册成默认实现。 当客户端调用com.nokia.qt.examples.FileStorage的实现时,FileStorageService 服务会被加载。 如果FileStorageService对同一个接口 注册了多个实现或版本,这个接口的最新版本将作为默认实现被加载。 因此接口的不同版本间需要保持二进制兼容性。

service管理器对象的当前作用域决定了 接口默认的指配是对所有用户有效还是只对当前用户有效。 用户作用域没有定义时讲使用系统默认。这使得用户可以自定义个人参数。当一个新的接口第一次安装服务时,默认设置为 system wide default selection。

基于QObject的服务

这是最常见的与servicer交互的方法。

 storage = manager.loadInterface("com.nokia.qt.examples.FileStorage");
if (storage)
QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt"));

上面的代码通过service的QMetaObject调用文件存储对象的deleteFile() 方法。客户端不需要知道对象的类型,因此也没有链接到具体的service库。

使用某种具体类型的服务

之前的查找机制都返回一个QObject指针。这个指针可以利用Qt的meta object系统来内省(introspect)对象。 当然在某些情况下,直接使用service对象更方便些,直接引用service的头文件,链接service提供方。这样做主要的好处是编译期检查。 缺点是客户端和service必须共享service对象的实现,链接库或者共享头文件。这样做违背了 服务框架(Service Framework )的设计原则,原意是分离客户端和服务,这样做之后两者就产生了关联,改变服务类型,需要同时改变服务和客户端。

下面的代码片段演示了大概的实现:

 #include <filestorage.h>
...
QServiceManager manager;
FileStorage *storage = 0;
...
storage = manager.loadLocalTypedInterface<FileStorage>("com.nokia.qt.examples.FileStorage");
if (storage)
storage->deleteFile("/tmp/readme.txt");

服务作用域

QServiceManager 在用户作用域或系统作用域中操作。默认在用户作用域。作用域的选择决定服务是对全局有效或只是对当前的用户有效, 查找服务和接口时是在全局服务集合中查找,还是全局服务并上当前用户的服务集合中查找。

用户作用域

在用户作用域, 服务注册在当前用户注册的存储点。当使用setInterfaceDefault()设置一个接口的默认服务时,服务可以是用户特有的或全局的服务。

查找服务和接口时,管理器会优先搜索用户特有的服务,没有找到时,在用户有权限时再查找全局的服务。


在服务被添加,删除时放送信号QServiceManager::serviceAdded()QServiceManager::serviceRemoved()。这些信号可以指定作用域参数。(只有当用户有足够的权限时才会得到全局服务的增减信号)

系统作用域

在系统作用域,服务注册在全局存储点。管理器不访问用户特定的操作。服务和接口在全局服务中找不到就返回fail。服务只注册在全局存储点,如果使用setInterfaceDefault()注册一个用户特定的服务,则返回fail。 QServiceManager::serviceAdded() 和QServiceManager::serviceRemoved()只发送全局服务的增减信号。


'增加,移除服务’

服务可以在运行期安装和移除。用一个XML文件来描述服务的meta data,通过meta data的描述来链接服务的代码。

XML格式

使用XML描述的 meta data和服务的位置来安装服务,XML文件的文件类型定义如下:

 <!ELEMENT SFW ( service ) >
<!ATTLIST SFW version (1.0|1.1) #REQUIRED >
<!ELEMENT service ( name, filepath | ipcaddress, description?, interface+ ) >
<!ELEMENT description ( #CDATA ) >
<!ELEMENT filepath ( #PCDATA ) >
<!ELEMENT ipcaddress ( #PCDATA ) >
<!ELEMENT interface ( name, version, description?, capabilities?, customproperty* ) >
<!ELEMENT capabilities ( #PCDATA ) >
<!ELEMENT name ( #PCDATA ) >
<!ELEMENT version ( #PCDATA ) >
<!ELEMENT customproperty ( #CDATA ) >
<!ATTLIST customproperty key NMTOKEN #REQUIRED >

元素和属性的意义如下:

SubElement |Description
|



The service framework XML version tag that encapsulates the service XML. Must provide the version attribute that follows the major.minor notation and must equate to supported Qt Service Framework versions. This means the minimum version is 1.0 however users are recommended to always specify the highest available version.
service


The service tag can contain an arbitrary number of interface tags and one description tag.
"


description


A user readable description of the purpose of the service.
"


filepath


The absolute path and name of the plug-in to be loaded when this service is requested. Alternatively if the plug-in name only is provided the standard library paths (see QCoreApplication::libraryPaths()) are used to find the plug-in. Note that if the plugin name is given only, platform specific parts such as the suffix ".dll" and ".so" or plugin prefix "lib" should be removed to enable cross platform resolution. QLibrary is used to determine the platform specific parts of the plugin.
" ipcaddress The socket name or path that the inter-process service will be published on that will provide clients with remote access. Should be the same name as the executable for the service without any suffix such as ".exe" etc.
"


name


The name of the service.
interface


The interface describes the properties of the interface.
"


capabilities


This property is a list of arbitrary strings which are interpreted as permissions/capabilities. The list elements are comma-separated and spaces after commas are not permitted. This list can be empty.
"


name


The name of the interface using the Java class name notation. (e.g. com.nokia.qt.TestService)
"


version


This property contains the interface and implementation version. The version tag follows the major.minor notation. The major version indicates the interface version the minor version the implementation version.

The version number must be greater than 1.0. The version cannot be less than 1.0 because the Service Framework is dependent on the fact that services must be binary compatible between major versions, and services with versions less than 1.0 are unlikely to be binary compatible with later versions.

"


description


A user readable description of the purpose of the interface.
"


customproperty


An implementation specific key value pair which can be used for filtering or as description.

相关链接

561 page views in the last 30 days.
×