Difference between revisions of "Zh/Uno/FAQ"
Zhangxiaofei (Talk | contribs) |
Zhangxiaofei (Talk | contribs) m (Uno/FAQ zh moved to Zh/Uno/FAQ) |
||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | [[Uno/FAQ|en]] | ||
+ | |||
关于Uno, UDK, URE等相关的常见问题。基于在dev@udk.openoffice.org邮件列表中提出的问题与回答。如果您有任何评论或问题,在那里提出同样可以得到答复。 | 关于Uno, UDK, URE等相关的常见问题。基于在dev@udk.openoffice.org邮件列表中提出的问题与回答。如果您有任何评论或问题,在那里提出同样可以得到答复。 | ||
==普遍问题== | ==普遍问题== | ||
===嘿,OpenOffice.org的组件技术真棒。我怎样才能参与进来?=== | ===嘿,OpenOffice.org的组件技术真棒。我怎样才能参与进来?=== | ||
− | 好极了,我们永远欢迎您。关于帮助的切入点请参阅[[Uno/To-Dos | 开放任务列表]] | + | 好极了,我们永远欢迎您。关于帮助的切入点请参阅[[Uno/To-Dos | 开放任务列表]]。如果您对于其中的任何任务有任何疑问请不要犹豫提出来。把它发到[http://udk.openoffice.org/servlets/SummarizeList?listName=dev dev@udk.openoffice.org]. |
===UNO依赖于OpenOffice.org吗?=== | ===UNO依赖于OpenOffice.org吗?=== | ||
− | 不久的将来,在OpenOffice.org的安装包之外将会有一个办公软件开发工具包(Office Development Kit)可供下载,这个开发工具包包含编译组件所需要的所有文件(头文件,库,工具软件,等等)。开发工具包也将包含示例。这些示例的makefile只需要有gnumake就可以编译(而不需要整个OpenOffice.org编译环境) | + | 不久的将来,在OpenOffice.org的安装包之外将会有一个办公软件开发工具包(Office Development Kit)可供下载,这个开发工具包包含编译组件所需要的所有文件(头文件,库,工具软件,等等)。开发工具包也将包含示例。这些示例的makefile只需要有gnumake就可以编译(而不需要整个OpenOffice.org编译环境)。可以用这些makefile作为模板来把您的UNO组件集成到您的编译环境里。 |
===UNO是不是和微软的COM技术类似?=== | ===UNO是不是和微软的COM技术类似?=== | ||
是的,UNO可以看作完全独立于办公软件本身的组件模型。它与COM是直接的竞争关系,您可以在[http://udk.openoffice.org/common/man/uno.html 这里]找到它所具有特性的列表。 | 是的,UNO可以看作完全独立于办公软件本身的组件模型。它与COM是直接的竞争关系,您可以在[http://udk.openoffice.org/common/man/uno.html 这里]找到它所具有特性的列表。 | ||
===什么是ODK?=== | ===什么是ODK?=== | ||
− | + | 办公软件开发工具包(ODK)在UDK的基础上增加了文档,API(更多IDL文件),以及示例。UDK是ODK的一个子集。如果您想要扩展OpenOffice.org的功能,或用OpenOffice.org制作解决方案,ODK将适合您的需要。UDK是一个独立的对象模型,可以脱离OpenOffice.org单独使用。在向Gnome以及XPCOM中集成,以达到统一开源对象模型(Open Source Object Model)的长期目标的过程中,UDK将是主要的讨论对象。未来,应该可以编写依赖于ODK的组件和独立于OpenOffice.org的组件。 | |
− | 办公软件开发工具包使软件工程师可以不需要笨重的OpenOffice.org编译环境就可以为OpenOffice.org开发组件。因此,ODK包含基本(以及重要的)库的二进制文件,C++头文件,所有的idl文件,.jar文件以及开发工具(代码生成器,组件注册工具,等等)。ODK还将包含一些源码与makefile,只要有gnumake和一个C++ | + | 办公软件开发工具包使软件工程师可以不需要笨重的OpenOffice.org编译环境就可以为OpenOffice.org开发组件。因此,ODK包含基本(以及重要的)库的二进制文件,C++头文件,所有的idl文件,.jar文件以及开发工具(代码生成器,组件注册工具,等等)。ODK还将包含一些源码与makefile,只要有gnumake和一个C++编译器就可以编译,您可以用这些makefile作为例子集成到您的编译环境里。未来,随每个版本的OpenOffice.org都会提供开发工具包并可以独立[http://download.openoffice.org/index.html#sdk 下载]。 |
===你们为什么不用Java或CORBA做中间件?=== | ===你们为什么不用Java或CORBA做中间件?=== | ||
− | 我们需要的中间件可以用于细粒度组件,至少是进程内组件。在同一种语言中使用不同的UNO组件是不应当有开销的(例如,在C++ | + | 我们需要的中间件可以用于细粒度组件,至少是进程内组件。在同一种语言中使用不同的UNO组件是不应当有开销的(例如,在C++中只是调用一个虚函数)。不幸的是,目前CORBA没有进程内组件的接口与数据结构的设计。唯一的通信方法是通过IIOP协议。对于进程内通信,这种开销实在太大。我们想要语言无关,让UNO作为像Java,C++,C和其它不同语言间的中介,这并不是CORBA的目标。UNO的另一个目标是成为像COM/DCOM,CORBA,Java和XPCOM这些不同对象模型间的中介,这也不是其它对象模型所具有的目标。 |
===UNO和CORBA间有什么不同点?=== | ===UNO和CORBA间有什么不同点?=== | ||
− | UNO不生成桩代码(stub | + | UNO不生成桩代码(stub code)。在过去UNO2的实现中我们是生成的。那时的一个问题是,生成的桩代码非常大(尽管当时的API数据类型比现在还要少,大概也有12MB!)在UNO3(现在的版本)中,我们决定泛型地调用具体实现部分。给C++生成的,除去纯虚类只有用来返回数据类型的getCppuType()函数。完整的数据类型描述是在运行时从一个二进制仓库中读取的。在数据类型数量增加的情况下,这种方法具有空间开销小的优点。如果想了解UNO和CORBA间的更多不同点,请参考以下[http://udk.openoffice.org/common/man/comparison_uno_corba.html 对比]。 |
===UNO IDL和CORBA IDL间有什么不同点?=== | ===UNO IDL和CORBA IDL间有什么不同点?=== | ||
UNO IDL具有: | UNO IDL具有: | ||
− | * | + | *数据结构(structure)与异常(exception)的继承关系 |
+ | *一种新的服务(service)类型 | ||
+ | *可以给枚举(enumeration)值赋具体的值 | ||
+ | *没有数组(array)类型(但为此引入了序列(sequence)) | ||
+ | *没有共用体(union)类型 | ||
===我能把OpenOffice.org组件当作Java Beans使用吗?=== | ===我能把OpenOffice.org组件当作Java Beans使用吗?=== | ||
+ | 可以,OpenOffice.org bean(OOoBean)项目使OpenOffice.org组件可以用于Java应用程序。请访问[http://wiki.services.openoffice.org/wiki/OOoBean OOoBean]以获得相关信息、源码、以及二进制档的下载。 | ||
+ | OOo Bean具有一下特点: | ||
+ | *将OpenOffice.org组件嵌入Java应用程序(application)或(applet)中。 | ||
+ | *可以通过Java访问全部StarOffice API,来编写您自己的应用程序。 | ||
+ | 这个项目刚刚开始,因此请留意可能存在的bug、不完整的文档以及安装问题等等。我们欢迎每位对OpenOffice.org和Java感兴趣的人士参与到项目中来,或是在他们的应用程序中使用OOoBean。 | ||
==开发相关问题== | ==开发相关问题== | ||
+ | ===能给我些代码示例吗?=== | ||
+ | ====C++示例==== | ||
+ | {|border="1" cellspacing="0" class="wikitable" cellpadding=3 | ||
+ | |- style="background:#efefef;" | ||
+ | | 位置 || 内容 | ||
+ | |- | ||
+ | |[http://www.openoffice.org/source/browse/udk/remotebridges/examples/officeclient.cxx udk/remotebridges/examples/officeclient.cxx] || 这个示例说明了如何建立到OpenOffice.org文档的进程间桥接(bridge)。 | ||
+ | 无论您的组件是用于Windows还是Linux,编写上都不存在区别。 | ||
+ | |- | ||
+ | |[http://www.openoffice.org/source/browse/udk/product/examples/ udk/product/examples/] || 更多示例。 | ||
+ | |- | ||
+ | |} | ||
+ | ====HTML 文档==== | ||
+ | {|border="1" cellspacing="0" class="wikitable" cellpadding=3 | ||
+ | |- style="background:#efefef;" | ||
+ | | 位置 || 内容 | ||
+ | |- | ||
+ | |http://udk.openoffice.org/cpp/man/tutorial/remotedemo.html || 远程通信demo教程。 | ||
+ | |- | ||
+ | |http://udk.openoffice.org/cpp/man/component_tutorial.html || 在UNO空间中编写的组件。 | ||
+ | |- | ||
+ | |http://udk.openoffice.org/cpp/man/tutorial/unointro.html || C++ UNO指南。 | ||
+ | |- | ||
+ | |http://udk.openoffice.org/common/man/concept/unointro.html || 编程语言无关的UNo指南。 | ||
+ | |} | ||
+ | ====Java示例==== | ||
+ | 我们缺少一篇优秀的关于如何在Java下开始开发的文档。您可以直接查看源码。在jurt项目中也有一些示例,您可以使用以下命令导出到本地: | ||
+ | $ cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs co udk/jurt | ||
+ | 您可以在demo目录下的源码中找到一些示例。 | ||
+ | {|border="1" cellspacing="0" class="wikitable" cellpadding=3 | ||
+ | |- style="background:#efefef;" | ||
+ | | 位置 || 内容 | ||
+ | |- | ||
+ | |[http://www.openoffice.org/source/browse/udk/jurt/demo/com/sun/star/demo/TestOffice.java jurt/demo/com/sun/star/demo/TestOffice.java] || 启动一个进程间桥接并在office中新建几个文档。 | ||
+ | |- | ||
+ | |[http://www.openoffice.org/source/browse/udk/jurt/demo/com/sun/star/comp/demo/ jurt/demo/com/sun/star/comp/demo/] || 这里可以找到一些关于如何创建一个Java组件的样例代码。这个样例可以注册到一个office中并在这个office中运行。 | ||
+ | |} | ||
+ | 我们还建议参考sun开发者网络(http://developers.sun.com/),您可以点击Download SDK下载到StarOffice程序员教程。它包含了一些关于某些API问题的示例。关于office API更深入的问题的问题请通过[http://api.openoffice.org/servlets/ProjectMailingListList dev@api.openoffice.org]询问。 | ||
+ | ===如何生成C++数据类型定义?=== | ||
+ | #新建用来描述接口的.idl文件 | ||
+ | #使用unoidl生成.urd文件 | ||
+ | #使用regmerge将新数据类型合并到系统注册表中 | ||
+ | #使用cppumaker生成C++数据类型(在Java中使用javamaker) | ||
+ | #在Java中,编译生成的接口,将它们添加到您的CLASSPATH中 | ||
+ | ===regcomp是干什么用的?=== | ||
+ | unoild将IDL描述转换成一个二进制库的格式,每个IDL数据类型在运行时都需要这个数据类型信息。unoidl生成的输出文件只包含定义的数据类型的信息。它不包含所有数据类型的全部数据类型描述。因此,需要使用regmerge将新数据类型安装到类型库applicat.rdb中。如果某人开发一个UNO组件,他必须支持或输出一些管理用的函数(例如,component_writeInfo)。关于支持哪些服务以及实现的名称,开发者要在component_writeInfo函数里给出相关信息。之后服务管理器(service manager)将使用这些信息来生成组件的实例。因此,如果您开发您自己的组件,您必须将您的组件安装到运行时中去。用regcomp就可以做到这点。regcomp读取component_writeinfo函数,并利用这些信息进行一些管理工作。例如,这个组件支持的所有服务都将插入一个全局的SERVICES段中,这个段要被服务管理器用到。在这个段中建立了服务名与实现名的相互联系。在IMPLEMENTATIONS保留区中,您可以为您的组件找到一个正确的段,它的值等于在component_writeInfo函数中定义的键值。请查看一下您安装在office目录下的applicat.rdb。 | ||
+ | $ regview applicat.rdb /SERVICES | ||
+ | $ regview applicat.rdb /SERVICES/<service_name> | ||
+ | $ regview applicat.rdb /IMPLEMENTATIONS | ||
+ | $ regview applicat.rdb /IMPLEMENTATIONS/<implementation_name> | ||
+ | 因此,安装一个新组件的时候需要使用regcomp。在类型库中安装新数据类型的时候需要使用regmerge。 | ||
+ | ===哪里能找到OpenOffice.org API?=== | ||
+ | 请访问[http://api.openoffice.org/ API项目网站]。 | ||
+ | ===如何测试我自己的组件?=== | ||
+ | 如果您开发了一个新组件,最后会生成一个共享的动态链接库(DLL)。当接到请求使用您实现的服务时,将会载入这个DLL。为了让您的组件在OpenOffice.org中能够看到和使用到,需要把您的服务注册成一个外部组件。您需要按照下面步骤来做到这一点: | ||
+ | #将您的DLL拷贝到.../program目录下。 | ||
+ | #将regcomp工具拷贝到.../program目录下。您可以在UDK的cpputools模块中找到这个工具。 | ||
+ | #使用regcomp工具:<pre>$ regcomp -register -r applicat.rdb -c foo.dll</pre> | ||
+ | #如果您开发了自己的接口或数据类型,您需要将这些新数据类型注册到UNO类型库中。您需要UDK的registry模块中的regmerge工具来做到这点。unoidl工具会生成一个foo.urd文件,它包含了新数据类型。可以在您的组件的输出目录下找到这个文件。 | ||
+ | #使用regmerge工具:<pre>$ regmerge applicat.rdb /UCR foo.urd</pre>IDL数据类型中的所有数据类型定义都存放在保留键值UCR下面(UNO core reflection,UNO核心映射) | ||
+ | #组件与新数据类型注册后您就可以通过服务管理器为您的服务生成实例了。 | ||
+ | 使用basic,有一种既快又便捷的方法可以给一个新服务生成实例。新建一个basic脚本输入下面的代码: | ||
+ | Sub Main | ||
+ | s = createUnoService("YourSerivceName") | ||
+ | msgbox(s.dbg_supportedinterfaces) | ||
+ | End Sub | ||
+ | 如果实例化过程成功,对话框将显示对象支持的全部接口。 | ||
+ | 可以在这个目录下的README文件中找到更多信息http://www.openoffice.org/source/browse/udk/product/examples/ | ||
+ | ===一共存在几种桥接?=== | ||
+ | 目前存在4种桥接:C++桥接、Java桥接、[http://udk.openoffice.org/common/man/spec/urp.html UNO远程协议(URP)桥接]以及[http://api.openoffice.org/ IIOP桥接]。 | ||
+ | ===什么时候要用到桥接?=== | ||
+ | 如果您是在C++里开发组件,记得由同一个编译器编译的组件,在进程内相互调用,是不需要在接口间桥接的。组件加载器可以识别这一点并直接使用实现好的C++接口。但如果您使用脚本语言(例如basic)调用一个Java组件,或是使用远程UNO调用其它进程,就要用到桥接了。 | ||
+ | ===怎样给数据结构设置缺省值?=== | ||
+ | 给数据结构设置缺省值是不可以的,因为这些缺省值不能用在其它对象模型(例如CORBA)里。也不可以通过修改unoidl为数据结构生成的缺省构造函数给变量成员设置缺省值。生成的缺省内联构造函数可以在.hpp文件中找到。构造函数只能把给定的初始值赋给变量成员。 | ||
+ | ===嘿,我的组件崩溃了,是怎么回事?=== | ||
+ | 由于只从堆栈很难知道错误出在哪里,请尽可能地附上更多的信息。如果您幸运地恰好是这个服务的作者,您可以附上组件的实现代码以及生成对象实例的代码。如果组件不是您开发的,那您将不得不联系组件的开发者了。 | ||
+ | ===为什么说编写编译器相关的C++桥接令人头痛?=== | ||
+ | UNO的目标是为UNO组件的开发者和使用者提供最简单的语言绑定、最少的生成代码与最快的运行速度。用现在的技术可以达到这个目标。例如,在C++中调用不存在额外开销,因为一个从C++到C++的调用只是调用一个虚函数。编译时不会生成代码,调用是在运行时由桥接完成的。UNO C++语言绑定比其它绑定(CORBA、COM)更小。从另一个角度来说,写一个C++桥接是一件困难的事,但对于每一个编译器、操作系统和处理器只需要做一次。要做到语言绑定的确存在更简单的方法,但它们并不是更好的方法。乍看来,一个从C++到UNO的桥接是非常依赖于编译器与应用程序二进制接口(ABI)的,似乎根本不具有可移植性。然而必须说明的是,对于大多数编译器来说桥接的代码是非常相似的。主要的差异在于生成的虚函数地址表(vtable),进行C++虚函数调用,已经异常处理。 | ||
+ | ===如何为一个RISC CPU实现C++桥接?=== | ||
+ | 在RISC机器上,函数的形参是在寄存器中传递的,然而,C++桥接代码要操作一个C++层与UNO层之间的栈。想要知道这个问题是如何解决的,请参阅sunpro5 solaris sparc的桥接。寄存器的内容被直接压栈(扩展了栈中的非寄存器参数[在多于6个的情况下])。 | ||
+ | ===载入一个文档时该使用哪个属性值(PropertyValue)?=== | ||
+ | 一个文档总是由加载器用一个空属性实参打开的 | ||
+ | PropertyValue [] szEmptyArgs = new PropertyValue [0]; | ||
+ | String doc = "private:factory/swriter"; | ||
+ | aDoc = oCLoader.loadComponentFromURL(doc, "_blank", 0, szEmptyArgs ); | ||
+ | 用这些参数,可以强制让OpenOffice.org使用某个特定的过滤器(filter),只读方式打开文档,为密码保护的文档设置密码。给spreadsheet用的csv过滤器有一些附件的选项,这些选项与UI中的pick list相同,这些选项被存放在soffice.ini/sofficerc中。 | ||
+ | ===如何打开一个文档并将它保存为HTML格式?=== | ||
+ | 可以使用下面的代码样例: | ||
+ | PropertyValue [] mypv = new PropertyValue[1]; | ||
+ | mypv[0] = new PropertyValue(); | ||
+ | mypv[0].Name = new String("FilterName"); | ||
+ | mypv[0].Value = new String("scalc: Text - txt"); | ||
+ | mypv[0].Handle = -1; | ||
+ | mypv[0].State = PropertyState.DEFAULT_VALUE; | ||
+ | aStore.storeAsURL(doc, mypv); //aStore is a XStorable object, and doc is url string | ||
+ | ===如何把OpenOffice.org文档保存为XML格式?=== | ||
+ | 可以使用下面的代码样例: | ||
+ | sub SaveXML | ||
+ | dim mProps(0) as new com.sun.star.beans.PropertyValue | ||
+ | mProps(0).Name = "FilterName" | ||
+ | 'This works with 614 | ||
+ | mProps(0).Value = "swriter: StarOffice XML (Writer)" | ||
+ | oDesk = createUNOService("com.sun.star.frame.Desktop") | ||
+ | 'For some reason, ActiveComponent no longer works: | ||
+ | oComponent = oDesk.CurrentComponent() | ||
+ | oComponent.storeAsUrl("file:///C|/Tmp/startemp.xml",_ | ||
+ | mProps()) | ||
+ | end sub | ||
+ | ===是不是每次都要用queryInterface?=== | ||
+ | 不需要直接调用queryInterface。更方便的方法是使用一个特殊的引用构造函数模板。不使用 | ||
+ | ::com::sun::star::uno::Any x = xI->queryInterface( | ||
+ | ::getCppuType((const ::com::sun::star::uno::Reference< | ||
+ | ::com::sun::star::i18n::XTransliteration>*)0)); | ||
+ | x >>= transRef; | ||
+ | 而使用: | ||
+ | transRef = Reference< XTransliteration >( xI, UNO_QUERY ); | ||
+ | ===cannot dump'com/star/uno/RuntimeException'是什么意思?=== | ||
+ | 首先,确认您按照FAQ条目的[[Uno/FAQ_zh#.E5.A6.82.E4.BD.95.E7.94.9F.E6.88.90C.2B.2B.E6.95.B0.E6.8D.AE.E7.B1.BB.E5.9E.8B.E5.AE.9A.E4.B9.89.EF.BC.9F | '如何生成C++数据类型定义?']]做了每一步。也就是说,您新建了一个“描述”或“定义”组件的.idl文件。您使用unoidl工具编译了idl文件。对生成的.urd文件运行了cppumaker。cppumaker为idl类型生成了一个C++的表示,并且它可以在unoidl生成的类型库上使用。如果您按照这些步骤去做产生了这个错误:cppumaker ERROR: cannot dump type 'com/star/uno/RuntimeException',您必须将您的新数据类型集成到系统类型库中,因为类型信息在运行时和生成C++代码时都需要用到。集成的最简单方法是把您的‘XXX.urd’文件合并到系统类型库中。系统类型库叫做applicat.rdb,可以在program目录下找到。要合并类型库,您必须使用regmerge工具,您可以在编译环境中找到它。applicat.rdb中的所有类型信息都保存在一个叫'UCR'的保留区中。您也必须把您自己的类型合并到这个保留区中。使用regmerge: | ||
+ | $ regmerge applicat.rdb /UCR yourtypes.urd | ||
+ | 还有一个很好的工具可以查看一个注册表文件(也就是类型库)的内容: | ||
+ | $ regview applicat.rdb /UCR/com/sun/star/uno | ||
+ | 上面的命令可以显示模块com.sun.star.uno中的所有数据类型,或者: | ||
+ | $ regview applicat.rdb /UCR/com/sun/star/uno/XInterface | ||
+ | 可以显示com.sun.star.uno.XInterface的类型信息。 | ||
+ | |||
+ | 关于生成的代码还有一点知识:cppumaker需要全部的类型信息,因为cppumaker要生成指定的数据类型和所有的依赖关系。被依赖的数据类型将递归地生成,使您能获得构建组件所需的全部C++声明。 | ||
+ | 使用regmerge之后,applicat.rdb包含了OpenOffice.org附带的以及您添加的全部数据类型。注意regmerge只修改第一个文件,其它文件是只读方式打开的。 | ||
+ | |||
+ | 现在您可以用regview检查一下regmerge是否成功,它是否已经包含您的新数据类型了。例如: | ||
+ | $ regview applicat.rdb /UCR/com/sun/star/uno/RuntimeException | ||
+ | 应当输出正常的RuntimeException。 | ||
+ | $ regview applicat.rdb /UCR/your/new/types | ||
+ | 应当输出您的新数据类型(当然,别忘了用新数据类型在idl中的模块和类型名替换上面的your/new/types)。 | ||
+ | |||
+ | 然后下面的命令应当可以会在您当前目录下生成C++头文件: | ||
+ | $ cppumaker -O. -Tyour/new/types -BUCR applicat.rdb | ||
+ | 如果不起作用,至少下面的命令应该起作用: | ||
+ | $ cppumaker -O. -Tcom/sun/star/uno/RuntimeException -BUCR applicat.rdb | ||
+ | ===symbol"component_geImplementationEnvironment"could not be found是什么意思?=== | ||
+ | 如果您像下面这样用regcomp注册您的DLL: | ||
+ | $ regcomp -register -r applicat.rdb -c foo.dll | ||
+ | 而得到了下面的错误: | ||
+ | register component "foo.dll" in registry "applicat.rdb" failed! | ||
+ | ERROR: component could not be registered: symbol "component_getImplementationEnvironment" | ||
+ | could not be found in "foo.dll" | ||
+ | 确认您的函数是在a.cxx中的任何类外定义的,像下面这样: | ||
+ | extern "C" | ||
+ | void SAL_CALL component_getImplementationEnvironment( | ||
+ | const sal_Char ** ppEnvTypeName, | ||
+ | uno_Environment ** ppEnv ) | ||
+ | { | ||
+ | *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; | ||
+ | } | ||
+ | 如果您没有使用模块定义文件(module definition file,DEF file),那么您可以在您的函数定义之前使用SAL_DLLEXPORT宏,它会展开成__declspec(dllexport)。在Win32平台上使用下面命令检查您的输出: | ||
+ | $ dumpbin /EXPORTS foo.dll | ||
+ | 如果在注册您的DLL时还不起作用,确认您的路径是否正确,所有的foo.dll链接到的库是否可以从您的路径访问到。在Win32平台上您可以使用Developer Studio 6附带的一个工具。它叫做depend,可以显示库的导入情况以及丢失的库(标记为红色)。如果这还没有用,您应当调试一下共享库组件加载器的writeRegistryInfo()函数。这个加载器位于CVS的stoc模块中,这个模块可以从oo/udk/stoc导出到本地。加载器是在stoc/source/loader中编译的。编译后的库叫做cpld.dll。 | ||
+ | ===如何恢复我用regmerge添加过条目的类型库?=== | ||
+ | regmerge在在写入时覆盖了原有的键值。不过如果有一个工具可以删除已存在的键值会很好,但目前还没有。 | ||
+ | ===如何在类型库中找到服务的描述?=== | ||
+ | 服务的描述没有保存在类型库中,因为运行时不需要反映服务的信息。服务描述存在的目的只是为了建立模型。 | ||
+ | 您可以用一个专门的选项(-C)启动IDL编译器来生成包含服务描述与注释的类型库,在正常的office版本中不这样用,因为这样库会变成大约两倍大。 | ||
+ | ===如何新建一个unique uik number?=== | ||
+ | 有些人只是找一个已有的,拷贝过来修改一下。我们当然不建议这样做,不过这样做也没有问题。目前我们还没有自己的工具,不过您可以使用微软编译器附带的guidgen.exe。 | ||
+ | |||
+ | 不过,目前guid没有用到。它们的存在是由于历史的原因(旧的UNO组件模型需要它),我们保留了它给未来的某种需要唯一性标识符的桥接——也许是UNO-COM——使用。 | ||
+ | ===如何配置office使它以侦听模式启动?=== | ||
+ | 有两种方法: | ||
+ | #启动office时使用附加参数:<pre>soffice -accept=socket,host=0,port=2002;urp;StarOffice.ServiceManager</pre>(在Unix shell下请把;分隔的句子包含到引号中) | ||
+ | #把上面字符串中的'-accept='去掉,放到配置文件里。您可以编辑<pre><office-install>/share/config/registry/instance/org/openoffice/Setup.xml</pre>把标签<pre><ooSetupConnectionURL cfg:type="string"/></pre>更换成<pre><ooSetupConnectionURL cfg:type="string">socket,host=0,port=2002;urp;StarOffice.ServiceManager</ooSetupConnectionURL></pre> | ||
+ | 请注意,这个修改会影响到整个网络安装,可能会成为一个非常严重的安全问题。还请注意,使用host=0会使office侦听每个网络接口,如果您只要在一台机器上调试您的office,将0换成localhost绝对更安全。 | ||
+ | |||
+ | (在网络安装中)如果要只为某个特定的用户设置远程连接,您需要在用户的配置目录下修改上面的Setup.xml。 | ||
+ | ===如何启动TestOffice.java?=== | ||
+ | 请使用类似uno:socket,host=localhost,port=2002;urp;StarOffice.NamingService的参数。 | ||
+ | ===如何远程连接到运行在另一台机器上的OpenOffice.org?=== | ||
+ | 连接到OpenOffice.org时要提供一个UNO URL,它可以定位到另一个进程中的一个已命名的UNO对象。一个UNO URL包含四个部分: | ||
+ | *字符串常量“uno”。 | ||
+ | *一个连接说明,附带可选的键值对形式的参数。 | ||
+ | *一个协议说明,附带可选的键值对形式的参数。 | ||
+ | *要定位的对象名。 | ||
+ | 将这四部分连接成一个字符串 | ||
+ | uno:[connection],params;[protocol],params;[objectname] | ||
+ | 一个UNO URL的示例像下面这样: | ||
+ | uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager | ||
+ | 关于UNO URL的更多信息请参阅http://udk.openoffice.org/common/man/spec/uno-url.html | ||
+ | 在对office实例化时,使用一个类似UNO URL的字符串来配置接受进程。您可以这样启动office: | ||
+ | soffice "-accept=socket,host=0,port=2002;urp;" | ||
+ | 注意这个字符串不像UNO URL定义那样严格,其它程序可能定义它们自己的格式(例如,ODK附带的UNO工具要使用一种不同的格式)。socket连接的一个特别之处是,您可以使用“host=0”,它表示接受当前机器上包括localhost在内的每个可用的网络接口。“host=0”部分不能用来连接一个资源。 | ||
+ | |||
+ | 并且,您不需要指明对象名,因为不论是否指明,office都会输出多个对象(StarOffice.NamingService,StarOffice.ServiceManager和[新的]StarOffice.ComponentContext)。 | ||
+ | ===UnoUrlResolver的作用是什么?=== | ||
+ | UnoUrlResolver通过一个在UNO URL中指定的服务名取得一个远程对象,尤其是一个StarOffice.ServiceManager。然后,使用服务管理器的XNamingService接口,通过getRegisteredObject返回服务管理器'registeredObject',以便能用queryInterface()获取一个XMultiServiceFactory。记住远程OpenOffice.org进程的启动阶段在返回名字服务(naming service)的引用之前已经完成了。这样才能保证所有服务都可用。要知道,名字服务只是给服务管理器用的容器。这样做是为了灵活性,因为未来的版本可能会输出更多对象,而不是只输出服务管理器。要把UNO URL理解成到另一个进程的入口;之后所有事情都通过普通的UNO调用处理。未来的版本可能会删除名字服务的删除和添加对象的能力,这对于远程进程显然说不通。 | ||
+ | ===如何在一个远程桥接被销毁时获得通知事件?=== | ||
+ | 一个XComponent在被销毁时会通知它的事件侦听器。不幸的是一个UnoUrlResolver对象无法接收销毁事件通知。至少需要一个连接器(connector)和一个桥接工厂(请参考jurt目录下的com.sun.star.comp.urlresolver.UnoUrlResolver以了解更多细节),这样您能够查找到一个XComponent接口。这个查找到的引用可以用来添加一个销毁事件侦听器,像下面这样: | ||
+ | String connection = "socket,host=localhost,port=2002"; | ||
+ | String protocol = "urp"; | ||
+ | Object connector = _xMultiServiceFactory.createInstance("com.sun.star.connection.Connector"); | ||
+ | XConnector connector_xConnector = (XConnector)UnoRuntime.queryInterface(XConnector.class, connector); | ||
+ | XConnection xConnection = connector_xConnector.connect(connection); | ||
+ | xBridge = xBridgeFactory.createBridge(connection + ";" + protocol, protocol, xConnection, null); | ||
+ | XComponent component = (XComponent)UnoRuntime.queryInterface(XComponent.class, component); | ||
+ | component.addEventListener(...); | ||
==文档相关问题== | ==文档相关问题== | ||
+ | ===如何导出UDK WWW文档?=== | ||
+ | 通过http://udk.openoffice.org/ 能浏览到的UDK项目文档,可以使用下面的CVS命令导出: | ||
+ | $ cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www | ||
+ | 如果不需要生成的C++模块参考文档,您可以把下面的命令保存到一个脚本或批处理文件中,并在命令行下运行它: | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/common | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/cpp/man | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/java | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/images | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/documentation_structure.html | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/faq.html | ||
+ | cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/index.html | ||
+ | ===哪里可以找到关于UNO安全性模型的更多信息?=== | ||
+ | 请参阅http://udk.openoffice.org/common/man/concept/uno_security.html。 这篇草案的主要目的是提供一个广泛的API把已有的安全性实现封装起来,这篇草案基于Java安全性,它的文法可能发生改变。有些处在讨论中的细节被标成了红色,比如远程透明度(remote transparency)。 | ||
+ | ===哪里可以找到关于UNO CORBA桥接的更多信息?=== | ||
+ | 在UNO和CORBA间进行桥接绝不是一个小工程,因为两个组件模型基于不太的基本概念。因此在开始实现之前,我们写了处理这些根本性区别的方法。请参阅http://udk.openoffice.org/common/man/concept/uno_corba.html 获得更多信息。 | ||
+ | |||
+ | 这篇文档目前只包括我们在开发桥接中要处理的部分。在接下来的几星期里这篇文档应该会快速地增长。来自社区的任何关于UNO CORBA桥接的意见我们都很欢迎,讨论在dev@udk.openoffice.org中进行。 | ||
+ | 主要目标是得到一个CORBA桥接,它支持足以与GNOME桌面(http://www.gnome.org/ )通信所需的所有特性。在GNOME中使用的组件模型是Bonobo,它是在[http://www.gnome.org/projects/ORBit2/ ORBIT],一个开源CORBA ORB(Object Request Broker)上构建的。举例来说,CORBA-UNO桥接将使OpenOffice.org支持GNOME的脚本语言。 | ||
+ | |||
+ | 另一个目标是开发一个“广泛”的CORBA-UNO桥接,用它可以使用任意的ORB通信。这使OpenOffice.org可以无缝集成到任何CORBA环境中。 | ||
+ | ===哪里可以找到SOAP-UNO集成的更多信息?=== | ||
+ | 请参阅http://udk.openoffice.org/common/man/draft/soap.html | ||
+ | ===哪里可以找到关于OpenOffice.org Bonobo集成的更多信息?=== | ||
+ | 可以在http://whiteboard.openoffice.org/bonobo/ 找到一篇关于OpenOffice.org-Bonobo项目的概述。里面写了这个项目的动机与目标。我们在CVS中导入了一些代码,使OpenOffice.org成为一个给Nautilus之类的容器用的Bonobo服务器端。关于如何在组件技术的层面上拉近OpenOffice.org与GNOME,欢迎贡献您的想法与代码。 | ||
+ | |||
+ | |||
+ | [[category:ZH]] | ||
+ | [[category:中文]] |
Latest revision as of 15:20, 28 January 2009
关于Uno, UDK, URE等相关的常见问题。基于在dev@udk.openoffice.org邮件列表中提出的问题与回答。如果您有任何评论或问题,在那里提出同样可以得到答复。
Contents
- 1 普遍问题
- 2 开发相关问题
- 2.1 能给我些代码示例吗?
- 2.2 如何生成C++数据类型定义?
- 2.3 regcomp是干什么用的?
- 2.4 哪里能找到OpenOffice.org API?
- 2.5 如何测试我自己的组件?
- 2.6 一共存在几种桥接?
- 2.7 什么时候要用到桥接?
- 2.8 怎样给数据结构设置缺省值?
- 2.9 嘿,我的组件崩溃了,是怎么回事?
- 2.10 为什么说编写编译器相关的C++桥接令人头痛?
- 2.11 如何为一个RISC CPU实现C++桥接?
- 2.12 载入一个文档时该使用哪个属性值(PropertyValue)?
- 2.13 如何打开一个文档并将它保存为HTML格式?
- 2.14 如何把OpenOffice.org文档保存为XML格式?
- 2.15 是不是每次都要用queryInterface?
- 2.16 cannot dump'com/star/uno/RuntimeException'是什么意思?
- 2.17 symbol"component_geImplementationEnvironment"could not be found是什么意思?
- 2.18 如何恢复我用regmerge添加过条目的类型库?
- 2.19 如何在类型库中找到服务的描述?
- 2.20 如何新建一个unique uik number?
- 2.21 如何配置office使它以侦听模式启动?
- 2.22 如何启动TestOffice.java?
- 2.23 如何远程连接到运行在另一台机器上的OpenOffice.org?
- 2.24 UnoUrlResolver的作用是什么?
- 2.25 如何在一个远程桥接被销毁时获得通知事件?
- 3 文档相关问题
普遍问题
嘿,OpenOffice.org的组件技术真棒。我怎样才能参与进来?
好极了,我们永远欢迎您。关于帮助的切入点请参阅 开放任务列表。如果您对于其中的任何任务有任何疑问请不要犹豫提出来。把它发到dev@udk.openoffice.org.
UNO依赖于OpenOffice.org吗?
不久的将来,在OpenOffice.org的安装包之外将会有一个办公软件开发工具包(Office Development Kit)可供下载,这个开发工具包包含编译组件所需要的所有文件(头文件,库,工具软件,等等)。开发工具包也将包含示例。这些示例的makefile只需要有gnumake就可以编译(而不需要整个OpenOffice.org编译环境)。可以用这些makefile作为模板来把您的UNO组件集成到您的编译环境里。
UNO是不是和微软的COM技术类似?
是的,UNO可以看作完全独立于办公软件本身的组件模型。它与COM是直接的竞争关系,您可以在这里找到它所具有特性的列表。
什么是ODK?
办公软件开发工具包(ODK)在UDK的基础上增加了文档,API(更多IDL文件),以及示例。UDK是ODK的一个子集。如果您想要扩展OpenOffice.org的功能,或用OpenOffice.org制作解决方案,ODK将适合您的需要。UDK是一个独立的对象模型,可以脱离OpenOffice.org单独使用。在向Gnome以及XPCOM中集成,以达到统一开源对象模型(Open Source Object Model)的长期目标的过程中,UDK将是主要的讨论对象。未来,应该可以编写依赖于ODK的组件和独立于OpenOffice.org的组件。 办公软件开发工具包使软件工程师可以不需要笨重的OpenOffice.org编译环境就可以为OpenOffice.org开发组件。因此,ODK包含基本(以及重要的)库的二进制文件,C++头文件,所有的idl文件,.jar文件以及开发工具(代码生成器,组件注册工具,等等)。ODK还将包含一些源码与makefile,只要有gnumake和一个C++编译器就可以编译,您可以用这些makefile作为例子集成到您的编译环境里。未来,随每个版本的OpenOffice.org都会提供开发工具包并可以独立下载。
你们为什么不用Java或CORBA做中间件?
我们需要的中间件可以用于细粒度组件,至少是进程内组件。在同一种语言中使用不同的UNO组件是不应当有开销的(例如,在C++中只是调用一个虚函数)。不幸的是,目前CORBA没有进程内组件的接口与数据结构的设计。唯一的通信方法是通过IIOP协议。对于进程内通信,这种开销实在太大。我们想要语言无关,让UNO作为像Java,C++,C和其它不同语言间的中介,这并不是CORBA的目标。UNO的另一个目标是成为像COM/DCOM,CORBA,Java和XPCOM这些不同对象模型间的中介,这也不是其它对象模型所具有的目标。
UNO和CORBA间有什么不同点?
UNO不生成桩代码(stub code)。在过去UNO2的实现中我们是生成的。那时的一个问题是,生成的桩代码非常大(尽管当时的API数据类型比现在还要少,大概也有12MB!)在UNO3(现在的版本)中,我们决定泛型地调用具体实现部分。给C++生成的,除去纯虚类只有用来返回数据类型的getCppuType()函数。完整的数据类型描述是在运行时从一个二进制仓库中读取的。在数据类型数量增加的情况下,这种方法具有空间开销小的优点。如果想了解UNO和CORBA间的更多不同点,请参考以下对比。
UNO IDL和CORBA IDL间有什么不同点?
UNO IDL具有:
- 数据结构(structure)与异常(exception)的继承关系
- 一种新的服务(service)类型
- 可以给枚举(enumeration)值赋具体的值
- 没有数组(array)类型(但为此引入了序列(sequence))
- 没有共用体(union)类型
我能把OpenOffice.org组件当作Java Beans使用吗?
可以,OpenOffice.org bean(OOoBean)项目使OpenOffice.org组件可以用于Java应用程序。请访问OOoBean以获得相关信息、源码、以及二进制档的下载。 OOo Bean具有一下特点:
- 将OpenOffice.org组件嵌入Java应用程序(application)或(applet)中。
- 可以通过Java访问全部StarOffice API,来编写您自己的应用程序。
这个项目刚刚开始,因此请留意可能存在的bug、不完整的文档以及安装问题等等。我们欢迎每位对OpenOffice.org和Java感兴趣的人士参与到项目中来,或是在他们的应用程序中使用OOoBean。
开发相关问题
能给我些代码示例吗?
C++示例
位置 | 内容 |
udk/remotebridges/examples/officeclient.cxx | 这个示例说明了如何建立到OpenOffice.org文档的进程间桥接(bridge)。
无论您的组件是用于Windows还是Linux,编写上都不存在区别。 |
udk/product/examples/ | 更多示例。 |
HTML 文档
位置 | 内容 |
http://udk.openoffice.org/cpp/man/tutorial/remotedemo.html | 远程通信demo教程。 |
http://udk.openoffice.org/cpp/man/component_tutorial.html | 在UNO空间中编写的组件。 |
http://udk.openoffice.org/cpp/man/tutorial/unointro.html | C++ UNO指南。 |
http://udk.openoffice.org/common/man/concept/unointro.html | 编程语言无关的UNo指南。 |
Java示例
我们缺少一篇优秀的关于如何在Java下开始开发的文档。您可以直接查看源码。在jurt项目中也有一些示例,您可以使用以下命令导出到本地:
$ cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs co udk/jurt
您可以在demo目录下的源码中找到一些示例。
位置 | 内容 |
jurt/demo/com/sun/star/demo/TestOffice.java | 启动一个进程间桥接并在office中新建几个文档。 |
jurt/demo/com/sun/star/comp/demo/ | 这里可以找到一些关于如何创建一个Java组件的样例代码。这个样例可以注册到一个office中并在这个office中运行。 |
我们还建议参考sun开发者网络(http://developers.sun.com/),您可以点击Download SDK下载到StarOffice程序员教程。它包含了一些关于某些API问题的示例。关于office API更深入的问题的问题请通过dev@api.openoffice.org询问。
如何生成C++数据类型定义?
- 新建用来描述接口的.idl文件
- 使用unoidl生成.urd文件
- 使用regmerge将新数据类型合并到系统注册表中
- 使用cppumaker生成C++数据类型(在Java中使用javamaker)
- 在Java中,编译生成的接口,将它们添加到您的CLASSPATH中
regcomp是干什么用的?
unoild将IDL描述转换成一个二进制库的格式,每个IDL数据类型在运行时都需要这个数据类型信息。unoidl生成的输出文件只包含定义的数据类型的信息。它不包含所有数据类型的全部数据类型描述。因此,需要使用regmerge将新数据类型安装到类型库applicat.rdb中。如果某人开发一个UNO组件,他必须支持或输出一些管理用的函数(例如,component_writeInfo)。关于支持哪些服务以及实现的名称,开发者要在component_writeInfo函数里给出相关信息。之后服务管理器(service manager)将使用这些信息来生成组件的实例。因此,如果您开发您自己的组件,您必须将您的组件安装到运行时中去。用regcomp就可以做到这点。regcomp读取component_writeinfo函数,并利用这些信息进行一些管理工作。例如,这个组件支持的所有服务都将插入一个全局的SERVICES段中,这个段要被服务管理器用到。在这个段中建立了服务名与实现名的相互联系。在IMPLEMENTATIONS保留区中,您可以为您的组件找到一个正确的段,它的值等于在component_writeInfo函数中定义的键值。请查看一下您安装在office目录下的applicat.rdb。
$ regview applicat.rdb /SERVICES $ regview applicat.rdb /SERVICES/<service_name> $ regview applicat.rdb /IMPLEMENTATIONS $ regview applicat.rdb /IMPLEMENTATIONS/<implementation_name>
因此,安装一个新组件的时候需要使用regcomp。在类型库中安装新数据类型的时候需要使用regmerge。
哪里能找到OpenOffice.org API?
请访问API项目网站。
如何测试我自己的组件?
如果您开发了一个新组件,最后会生成一个共享的动态链接库(DLL)。当接到请求使用您实现的服务时,将会载入这个DLL。为了让您的组件在OpenOffice.org中能够看到和使用到,需要把您的服务注册成一个外部组件。您需要按照下面步骤来做到这一点:
- 将您的DLL拷贝到.../program目录下。
- 将regcomp工具拷贝到.../program目录下。您可以在UDK的cpputools模块中找到这个工具。
- 使用regcomp工具:
$ regcomp -register -r applicat.rdb -c foo.dll
- 如果您开发了自己的接口或数据类型,您需要将这些新数据类型注册到UNO类型库中。您需要UDK的registry模块中的regmerge工具来做到这点。unoidl工具会生成一个foo.urd文件,它包含了新数据类型。可以在您的组件的输出目录下找到这个文件。
- 使用regmerge工具:
$ regmerge applicat.rdb /UCR foo.urd
IDL数据类型中的所有数据类型定义都存放在保留键值UCR下面(UNO core reflection,UNO核心映射) - 组件与新数据类型注册后您就可以通过服务管理器为您的服务生成实例了。
使用basic,有一种既快又便捷的方法可以给一个新服务生成实例。新建一个basic脚本输入下面的代码:
Sub Main s = createUnoService("YourSerivceName") msgbox(s.dbg_supportedinterfaces) End Sub
如果实例化过程成功,对话框将显示对象支持的全部接口。 可以在这个目录下的README文件中找到更多信息http://www.openoffice.org/source/browse/udk/product/examples/
一共存在几种桥接?
目前存在4种桥接:C++桥接、Java桥接、UNO远程协议(URP)桥接以及IIOP桥接。
什么时候要用到桥接?
如果您是在C++里开发组件,记得由同一个编译器编译的组件,在进程内相互调用,是不需要在接口间桥接的。组件加载器可以识别这一点并直接使用实现好的C++接口。但如果您使用脚本语言(例如basic)调用一个Java组件,或是使用远程UNO调用其它进程,就要用到桥接了。
怎样给数据结构设置缺省值?
给数据结构设置缺省值是不可以的,因为这些缺省值不能用在其它对象模型(例如CORBA)里。也不可以通过修改unoidl为数据结构生成的缺省构造函数给变量成员设置缺省值。生成的缺省内联构造函数可以在.hpp文件中找到。构造函数只能把给定的初始值赋给变量成员。
嘿,我的组件崩溃了,是怎么回事?
由于只从堆栈很难知道错误出在哪里,请尽可能地附上更多的信息。如果您幸运地恰好是这个服务的作者,您可以附上组件的实现代码以及生成对象实例的代码。如果组件不是您开发的,那您将不得不联系组件的开发者了。
为什么说编写编译器相关的C++桥接令人头痛?
UNO的目标是为UNO组件的开发者和使用者提供最简单的语言绑定、最少的生成代码与最快的运行速度。用现在的技术可以达到这个目标。例如,在C++中调用不存在额外开销,因为一个从C++到C++的调用只是调用一个虚函数。编译时不会生成代码,调用是在运行时由桥接完成的。UNO C++语言绑定比其它绑定(CORBA、COM)更小。从另一个角度来说,写一个C++桥接是一件困难的事,但对于每一个编译器、操作系统和处理器只需要做一次。要做到语言绑定的确存在更简单的方法,但它们并不是更好的方法。乍看来,一个从C++到UNO的桥接是非常依赖于编译器与应用程序二进制接口(ABI)的,似乎根本不具有可移植性。然而必须说明的是,对于大多数编译器来说桥接的代码是非常相似的。主要的差异在于生成的虚函数地址表(vtable),进行C++虚函数调用,已经异常处理。
如何为一个RISC CPU实现C++桥接?
在RISC机器上,函数的形参是在寄存器中传递的,然而,C++桥接代码要操作一个C++层与UNO层之间的栈。想要知道这个问题是如何解决的,请参阅sunpro5 solaris sparc的桥接。寄存器的内容被直接压栈(扩展了栈中的非寄存器参数[在多于6个的情况下])。
载入一个文档时该使用哪个属性值(PropertyValue)?
一个文档总是由加载器用一个空属性实参打开的
PropertyValue [] szEmptyArgs = new PropertyValue [0]; String doc = "private:factory/swriter"; aDoc = oCLoader.loadComponentFromURL(doc, "_blank", 0, szEmptyArgs );
用这些参数,可以强制让OpenOffice.org使用某个特定的过滤器(filter),只读方式打开文档,为密码保护的文档设置密码。给spreadsheet用的csv过滤器有一些附件的选项,这些选项与UI中的pick list相同,这些选项被存放在soffice.ini/sofficerc中。
如何打开一个文档并将它保存为HTML格式?
可以使用下面的代码样例:
PropertyValue [] mypv = new PropertyValue[1]; mypv[0] = new PropertyValue(); mypv[0].Name = new String("FilterName"); mypv[0].Value = new String("scalc: Text - txt"); mypv[0].Handle = -1; mypv[0].State = PropertyState.DEFAULT_VALUE; aStore.storeAsURL(doc, mypv); //aStore is a XStorable object, and doc is url string
如何把OpenOffice.org文档保存为XML格式?
可以使用下面的代码样例:
sub SaveXML dim mProps(0) as new com.sun.star.beans.PropertyValue mProps(0).Name = "FilterName" 'This works with 614 mProps(0).Value = "swriter: StarOffice XML (Writer)" oDesk = createUNOService("com.sun.star.frame.Desktop") 'For some reason, ActiveComponent no longer works: oComponent = oDesk.CurrentComponent() oComponent.storeAsUrl("file:///C|/Tmp/startemp.xml",_ mProps()) end sub
是不是每次都要用queryInterface?
不需要直接调用queryInterface。更方便的方法是使用一个特殊的引用构造函数模板。不使用
::com::sun::star::uno::Any x = xI->queryInterface( ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XTransliteration>*)0)); x >>= transRef;
而使用:
transRef = Reference< XTransliteration >( xI, UNO_QUERY );
cannot dump'com/star/uno/RuntimeException'是什么意思?
首先,确认您按照FAQ条目的 '如何生成C++数据类型定义?'做了每一步。也就是说,您新建了一个“描述”或“定义”组件的.idl文件。您使用unoidl工具编译了idl文件。对生成的.urd文件运行了cppumaker。cppumaker为idl类型生成了一个C++的表示,并且它可以在unoidl生成的类型库上使用。如果您按照这些步骤去做产生了这个错误:cppumaker ERROR: cannot dump type 'com/star/uno/RuntimeException',您必须将您的新数据类型集成到系统类型库中,因为类型信息在运行时和生成C++代码时都需要用到。集成的最简单方法是把您的‘XXX.urd’文件合并到系统类型库中。系统类型库叫做applicat.rdb,可以在program目录下找到。要合并类型库,您必须使用regmerge工具,您可以在编译环境中找到它。applicat.rdb中的所有类型信息都保存在一个叫'UCR'的保留区中。您也必须把您自己的类型合并到这个保留区中。使用regmerge:
$ regmerge applicat.rdb /UCR yourtypes.urd
还有一个很好的工具可以查看一个注册表文件(也就是类型库)的内容:
$ regview applicat.rdb /UCR/com/sun/star/uno
上面的命令可以显示模块com.sun.star.uno中的所有数据类型,或者:
$ regview applicat.rdb /UCR/com/sun/star/uno/XInterface
可以显示com.sun.star.uno.XInterface的类型信息。
关于生成的代码还有一点知识:cppumaker需要全部的类型信息,因为cppumaker要生成指定的数据类型和所有的依赖关系。被依赖的数据类型将递归地生成,使您能获得构建组件所需的全部C++声明。 使用regmerge之后,applicat.rdb包含了OpenOffice.org附带的以及您添加的全部数据类型。注意regmerge只修改第一个文件,其它文件是只读方式打开的。
现在您可以用regview检查一下regmerge是否成功,它是否已经包含您的新数据类型了。例如:
$ regview applicat.rdb /UCR/com/sun/star/uno/RuntimeException
应当输出正常的RuntimeException。
$ regview applicat.rdb /UCR/your/new/types
应当输出您的新数据类型(当然,别忘了用新数据类型在idl中的模块和类型名替换上面的your/new/types)。
然后下面的命令应当可以会在您当前目录下生成C++头文件:
$ cppumaker -O. -Tyour/new/types -BUCR applicat.rdb
如果不起作用,至少下面的命令应该起作用: $ cppumaker -O. -Tcom/sun/star/uno/RuntimeException -BUCR applicat.rdb
symbol"component_geImplementationEnvironment"could not be found是什么意思?
如果您像下面这样用regcomp注册您的DLL:
$ regcomp -register -r applicat.rdb -c foo.dll
而得到了下面的错误:
register component "foo.dll" in registry "applicat.rdb" failed! ERROR: component could not be registered: symbol "component_getImplementationEnvironment" could not be found in "foo.dll"
确认您的函数是在a.cxx中的任何类外定义的,像下面这样:
extern "C" void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; }
如果您没有使用模块定义文件(module definition file,DEF file),那么您可以在您的函数定义之前使用SAL_DLLEXPORT宏,它会展开成__declspec(dllexport)。在Win32平台上使用下面命令检查您的输出:
$ dumpbin /EXPORTS foo.dll
如果在注册您的DLL时还不起作用,确认您的路径是否正确,所有的foo.dll链接到的库是否可以从您的路径访问到。在Win32平台上您可以使用Developer Studio 6附带的一个工具。它叫做depend,可以显示库的导入情况以及丢失的库(标记为红色)。如果这还没有用,您应当调试一下共享库组件加载器的writeRegistryInfo()函数。这个加载器位于CVS的stoc模块中,这个模块可以从oo/udk/stoc导出到本地。加载器是在stoc/source/loader中编译的。编译后的库叫做cpld.dll。
如何恢复我用regmerge添加过条目的类型库?
regmerge在在写入时覆盖了原有的键值。不过如果有一个工具可以删除已存在的键值会很好,但目前还没有。
如何在类型库中找到服务的描述?
服务的描述没有保存在类型库中,因为运行时不需要反映服务的信息。服务描述存在的目的只是为了建立模型。 您可以用一个专门的选项(-C)启动IDL编译器来生成包含服务描述与注释的类型库,在正常的office版本中不这样用,因为这样库会变成大约两倍大。
如何新建一个unique uik number?
有些人只是找一个已有的,拷贝过来修改一下。我们当然不建议这样做,不过这样做也没有问题。目前我们还没有自己的工具,不过您可以使用微软编译器附带的guidgen.exe。
不过,目前guid没有用到。它们的存在是由于历史的原因(旧的UNO组件模型需要它),我们保留了它给未来的某种需要唯一性标识符的桥接——也许是UNO-COM——使用。
如何配置office使它以侦听模式启动?
有两种方法:
- 启动office时使用附加参数:
soffice -accept=socket,host=0,port=2002;urp;StarOffice.ServiceManager
(在Unix shell下请把;分隔的句子包含到引号中) - 把上面字符串中的'-accept='去掉,放到配置文件里。您可以编辑
<office-install>/share/config/registry/instance/org/openoffice/Setup.xml
把标签<ooSetupConnectionURL cfg:type="string"/>
更换成<ooSetupConnectionURL cfg:type="string">socket,host=0,port=2002;urp;StarOffice.ServiceManager</ooSetupConnectionURL>
请注意,这个修改会影响到整个网络安装,可能会成为一个非常严重的安全问题。还请注意,使用host=0会使office侦听每个网络接口,如果您只要在一台机器上调试您的office,将0换成localhost绝对更安全。
(在网络安装中)如果要只为某个特定的用户设置远程连接,您需要在用户的配置目录下修改上面的Setup.xml。
如何启动TestOffice.java?
请使用类似uno:socket,host=localhost,port=2002;urp;StarOffice.NamingService的参数。
如何远程连接到运行在另一台机器上的OpenOffice.org?
连接到OpenOffice.org时要提供一个UNO URL,它可以定位到另一个进程中的一个已命名的UNO对象。一个UNO URL包含四个部分:
- 字符串常量“uno”。
- 一个连接说明,附带可选的键值对形式的参数。
- 一个协议说明,附带可选的键值对形式的参数。
- 要定位的对象名。
将这四部分连接成一个字符串
uno:[connection],params;[protocol],params;[objectname]
一个UNO URL的示例像下面这样:
uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager
关于UNO URL的更多信息请参阅http://udk.openoffice.org/common/man/spec/uno-url.html 在对office实例化时,使用一个类似UNO URL的字符串来配置接受进程。您可以这样启动office:
soffice "-accept=socket,host=0,port=2002;urp;"
注意这个字符串不像UNO URL定义那样严格,其它程序可能定义它们自己的格式(例如,ODK附带的UNO工具要使用一种不同的格式)。socket连接的一个特别之处是,您可以使用“host=0”,它表示接受当前机器上包括localhost在内的每个可用的网络接口。“host=0”部分不能用来连接一个资源。
并且,您不需要指明对象名,因为不论是否指明,office都会输出多个对象(StarOffice.NamingService,StarOffice.ServiceManager和[新的]StarOffice.ComponentContext)。
UnoUrlResolver的作用是什么?
UnoUrlResolver通过一个在UNO URL中指定的服务名取得一个远程对象,尤其是一个StarOffice.ServiceManager。然后,使用服务管理器的XNamingService接口,通过getRegisteredObject返回服务管理器'registeredObject',以便能用queryInterface()获取一个XMultiServiceFactory。记住远程OpenOffice.org进程的启动阶段在返回名字服务(naming service)的引用之前已经完成了。这样才能保证所有服务都可用。要知道,名字服务只是给服务管理器用的容器。这样做是为了灵活性,因为未来的版本可能会输出更多对象,而不是只输出服务管理器。要把UNO URL理解成到另一个进程的入口;之后所有事情都通过普通的UNO调用处理。未来的版本可能会删除名字服务的删除和添加对象的能力,这对于远程进程显然说不通。
如何在一个远程桥接被销毁时获得通知事件?
一个XComponent在被销毁时会通知它的事件侦听器。不幸的是一个UnoUrlResolver对象无法接收销毁事件通知。至少需要一个连接器(connector)和一个桥接工厂(请参考jurt目录下的com.sun.star.comp.urlresolver.UnoUrlResolver以了解更多细节),这样您能够查找到一个XComponent接口。这个查找到的引用可以用来添加一个销毁事件侦听器,像下面这样:
String connection = "socket,host=localhost,port=2002"; String protocol = "urp"; Object connector = _xMultiServiceFactory.createInstance("com.sun.star.connection.Connector"); XConnector connector_xConnector = (XConnector)UnoRuntime.queryInterface(XConnector.class, connector); XConnection xConnection = connector_xConnector.connect(connection); xBridge = xBridgeFactory.createBridge(connection + ";" + protocol, protocol, xConnection, null); XComponent component = (XComponent)UnoRuntime.queryInterface(XComponent.class, component); component.addEventListener(...);
文档相关问题
如何导出UDK WWW文档?
通过http://udk.openoffice.org/ 能浏览到的UDK项目文档,可以使用下面的CVS命令导出:
$ cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www
如果不需要生成的C++模块参考文档,您可以把下面的命令保存到一个脚本或批处理文件中,并在命令行下运行它:
cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/common cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/cpp/man cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/java cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/images cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/documentation_structure.html cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/faq.html cvs -d :pserver:anoncvs@anoncvs.services.openoffice.org:/cvs -z3 co udk/www/index.html
哪里可以找到关于UNO安全性模型的更多信息?
请参阅http://udk.openoffice.org/common/man/concept/uno_security.html。 这篇草案的主要目的是提供一个广泛的API把已有的安全性实现封装起来,这篇草案基于Java安全性,它的文法可能发生改变。有些处在讨论中的细节被标成了红色,比如远程透明度(remote transparency)。
哪里可以找到关于UNO CORBA桥接的更多信息?
在UNO和CORBA间进行桥接绝不是一个小工程,因为两个组件模型基于不太的基本概念。因此在开始实现之前,我们写了处理这些根本性区别的方法。请参阅http://udk.openoffice.org/common/man/concept/uno_corba.html 获得更多信息。
这篇文档目前只包括我们在开发桥接中要处理的部分。在接下来的几星期里这篇文档应该会快速地增长。来自社区的任何关于UNO CORBA桥接的意见我们都很欢迎,讨论在dev@udk.openoffice.org中进行。 主要目标是得到一个CORBA桥接,它支持足以与GNOME桌面(http://www.gnome.org/ )通信所需的所有特性。在GNOME中使用的组件模型是Bonobo,它是在ORBIT,一个开源CORBA ORB(Object Request Broker)上构建的。举例来说,CORBA-UNO桥接将使OpenOffice.org支持GNOME的脚本语言。
另一个目标是开发一个“广泛”的CORBA-UNO桥接,用它可以使用任意的ORB通信。这使OpenOffice.org可以无缝集成到任何CORBA环境中。
哪里可以找到SOAP-UNO集成的更多信息?
请参阅http://udk.openoffice.org/common/man/draft/soap.html
哪里可以找到关于OpenOffice.org Bonobo集成的更多信息?
可以在http://whiteboard.openoffice.org/bonobo/ 找到一篇关于OpenOffice.org-Bonobo项目的概述。里面写了这个项目的动机与目标。我们在CVS中导入了一些代码,使OpenOffice.org成为一个给Nautilus之类的容器用的Bonobo服务器端。关于如何在组件技术的层面上拉近OpenOffice.org与GNOME,欢迎贡献您的想法与代码。