Difference between revisions of "Zh/Documentation/DevGuide/ProUNO/Bridge/Automation Objects with UNO Interfaces"

From Apache OpenOffice Wiki
Jump to: navigation, search
 
Line 29: Line 29:
  
  
{{Documentation/Note|您永远不会实现 <idl>com.sun.star.script.XInvocation</idl> 和 <idl>com.sun.star.uno.XInterface</idl>。无法实现 <tt>XInvocatio</tt>,因为在内部桥已经将 <tt>IDispatch</tt> 映射成 <tt>XInvocation</tt>。假定存在一个需要 <tt>XInvocation</tt> 的函数:  
+
{{Note|您永远不会实现 <idl>com.sun.star.script.XInvocation</idl> 和 <idl>com.sun.star.uno.XInterface</idl>。无法实现 <tt>XInvocatio</tt>,因为在内部桥已经将 <tt>IDispatch</tt> 映射成 <tt>XInvocation</tt>。假定存在一个需要 <tt>XInvocation</tt> 的函数:  
  
 
   :// UNO IDL  
 
   :// UNO IDL  

Latest revision as of 16:58, 4 July 2018



UNO 函数将接口用作参数非常普遍。如 专业 UNO - UNO 语言绑定 - Automation 桥 - 类型的使用 一节中所讨论的那样,通常是通过 UNO 函数的返回值来获取那些对象。利用 Automation 桥,甚至可以将这些对象作为 Automation 对象进行实现,并可以将它们像 UNO 对象一样用作参数。


尽管 Automation 对象可以充当 UNO 对象,但它们还不是真正的 UNO 组件。也就是说,无法通过服务管理器创建 Automation 对象。并且没有定义 UNO 异常的映射。也就是说,作为 Automation 对象实现的 UNO 对象无法使用异常,也无法以其他任何方式传送异常。


此类对象的一种用例是侦听器。例如,如果一个客户机想知道一个 Writer 文档何时被关闭,它可以将侦听器对象注册到此文档,这样,文档关闭时就会通知该客户机。


要求

Automation 对象实现 IDispatch 接口,并且所有函数调用和属性操作都是通过此接口进行的。提到实现 UNO 接口的 Automation 对象,暗含着所有接口函数都是通过该分发接口进行访问的。也就是说,Automation 对象仍然只实现 IDispatch


基本上来说,只要可以将函数使用的数据类型映射成 Automation 类型,就可以实现所有 UNO 接口。桥需要知道 Automation 对象支持哪些 UNO 接口,这样桥就能够创建实现所有这些接口的 UNO 对象。这是通过要求 Automation 对象支持属性 Bridge_implementedInterfaces(一组字符串)完成的。每个字符串都是已实现接口的全限定名称。如果某个 Automation 对象仅实现一个 UNO 接口,则其不需要支持该属性。


Documentation note.png 您永远不会实现 com.sun.star.script.XInvocationcom.sun.star.uno.XInterface。无法实现 XInvocatio,因为在内部桥已经将 IDispatch 映射成 XInvocation。假定存在一个需要 XInvocation 的函数:
 :// UNO IDL 
 :void func( [in] com.sun.star.script.XInvocation obj);

在这种情况下,可将任意 Automation 对象用作参数。如果有一个接口提供此函数,

 :void func( [in] com.sun.star.XSomething obj) 

Automation 对象必须实现 XSomething 中的函数,这样就可以通过 IDispatch::Invoke 调用这些函数。


示例

以下示例说明如何在 VB 中实现 UNO 接口。它是一个侦听器的示例,当关闭 Writer 文档时,该侦听器会收到通知。


要重建项目,请使用 ActiveX dll 向导,并将该代码放在类模块中。该组件实现 com.sun.star.lang.XEventListener 接口。

 Option Explicit
 Private interfaces(0) As String
 
 Public Property Get Bridge_ImplementedInterfaces() As Variant
     Bridge_ImplementedInterfaces = interfaces
 End Property
 
 Private Sub Class_Initialize()
     interfaces(0) = "com.sun.star.lang.XEventListener"
 End Sub
 
 Private Sub Class_Terminate()
     On Error Resume Next
     Debug.Print "Terminate VBEventListener"
 End Sub
 
 Public Sub disposing(ByVal source As Object)
     MsgBox "disposing called"
 End Sub


可以像下面示例一样在 VB 中使用这些组件:

 Dim objServiceManager As Object
 Dim objDesktop As Object
 Dim objDocument As Object
 Dim objEventListener As Object
 
 Set objServiceManager= CreateObject("com.sun.star.ServiceManager")
 Set objDesktop= objServiceManager.createInstance("com.sun.star.frame.Desktop")
 
 'Open a new empty writer document
 Dim args()
 Set objDocument= objDesktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, args)
 'create the event listener ActiveX component
 Set objEventListener= CreateObject("VBasicEventListener.VBEventListener")
 
 'register the listener with the document
 objDocument.addEventListener objEventlistener


下一个示例说明一个 UNO 接口的 JScript 实现,以及如何通过 JScript 使用此接口。要将 JScript 与 UNO 配合使用,必须确定一种实现数组和 out 参数的方法。目前,如果 UNO 对象调用 JScript 对象,桥必须知道需要按照 JScript 要求转换参数。因此,桥必须知道有对象调用 JScript 组件,但桥无法查明使用的是什么语言。程序员必须提供提示,这是通过实现一个属性来完成的,该属性的名称为 “_environment”,其值为 "JScript"。

 // UNO IDL: the interface to be implemented
 interface XSimple : public com.sun.star.uno.XInterface
 {
     void func1( [in] long val, [out] long outVal);
     long func2( [in] sequence< long > val, [out] sequence< long > outVal);
     void func3( [inout]long);
 };
 // JScript: implementation of XSimple
 function XSimplImpl()
 {
     this._environment= "JScript";
     this.Bridge_implementedInterfaces= new Array( "XSimple"); 
 
     // the interface functions
     this.func1= func1_impl;
     this.func2= func2_impl;
     this.func3= func3_impl;
 }
 
 function func1_impl( inval, outval)
 {
     //outval is an array
     outval[0]= 10;
     ...
 }
 
 function func2_impl(inArray, outArray)
 {
     outArray[0]= inArray;
     // or 
     outArray[0]= new Array(1,2,3);
 
     return 10;
 }
 
 function func3_impl(inoutval)
 {
     var val= inoutval[0];
     inoutval[0]= val+1;
 }


假定有一个实现以下接口函数的 UNO 对象:

 //UNO IDL
 void doSomething( [in] XSimple);


现在,使用 JScript 语言调用此函数,并提供 XSimple 的 JScript 实现:

 <script language="JScript">
 
 var factory= new ActiveXObject("com.sun.star.ServiceManager");
 // create the UNO component that implements an interface with the doSomething function 
 var oletest= factory.createInstance("oletest.OleTest");
 oletest.doSomething( new XSimpleImpl());
 ...
 </script>


要用 C++ 构建一个组件,请从头编写此组件或使用一种框架,如动态模板库 (ATL)。将一个双接口与 ATL 配合使用时,实现 IDispatch 的过程是完全隐入的,而且必须实现函数,就像它们是普通的自定义接口一样,也就是说,使用特定类型作为参数,而不是使用 VARIANT。如果一个 UNO 函数具有返回值,则必须将返回值指定为第一个参数,并且设定其标志为 “retval”。

 // UNO IDL
 interface XSimple : public com.sun.star.uno.XInterface
 {
     void func1( [in] long val, [out] long outVal);
     long func2( [in] sequence< long > val, [out] sequence< long > outVal);
 };
 
 //IDL of ATL component
 [
     object,
     uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),
     dual,
     helpstring("ISimple Interface"),
     pointer_default(unique)
 ]
 interface ISimple : IDispatch
 {
     [id(1), helpstring("method func1")] 
                 HRESULT func1( [in] long val, [out] long* outVal);
     [id(2), helpstring("method func2")] 
                 HRESULT func2([out,retval] long ret, [in] SAFEARRAY(VARIANT) val, 
                         [out] SAFEARRAY(VARIANT) * outVal);
     [propget, id(4), helpstring("property_implementedInterfaces")] 
         HRESULT Bridge_implementedInterfaces([out, retval] SAFEARRAY(BSTR) *pVal);
 };
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages