Automation Objects with UNO Interfaces

From Apache OpenOffice Wiki
< Documentation‎ | DevGuide
Revision as of 12:25, 1 November 2007 by Jsc (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search



It is common that UNO functions take interfaces as arguments. As discussed in section Usage of Types, those objects are usually obtained as return values of UNO functions. With the Automation bridge, it is possible to implement those objects even as Automation objects and use them as arguments, just like UNO objects.

Although Automation objects can act as UNO objects, they are still not fully functional UNO components. That is, they cannot be created by means of the service manager. Also, there is no mapping of UNO exceptions defined. That is, an UNO object implemented as automation object cannot make use of exceptions nor can it convey them in any other way.

One use case for such objects are listeners. For example, if a client wants to know when a writer document is being closed, it can register the listener object with the document, so that it will be notified when the document is closing.

Requirements

Automation objects implement the IDispatch interface, and all function calls and property operations go through this interface. We imply that all interface functions are accessed through the dispatch interface when there is mention of an Automation object implementing UNO interfaces. That is, the Automation object still implements IDispatch only.

Basically, all UNO interfaces can be implemented as long as the data types used with the functions can be mapped to Automation types. The bridge needs to know what UNO interfaces are supported by an Automation object, so that it can create a UNO object that implements all those interfaces. This is done by requiring the Automation objects to support the property Bridge_implementedInterfaces, which is an array of strings. Each of the strings is a fully qualified name of an implemented interface. If an Automation object only implements one UNO interface, then it does not need to support that property.

Template:Documentation/Note

Examples

The following example shows how a UNO interface is implemented in VB. It is about a listener that gets notified when a writer document is being closed.

To rebuild the project use the wizard for an ActiveX dll and put this code in the class module. The component implements the com.sun.star.lang.XEventListener interface.

 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

You can use these components in VB like this:

 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

The next example shows a JScript implementation of a UNO interface and its usage from JScript. To use JScript with UNO, a method had to be determined to realize arrays and out parameters. Presently, if a UNO object makes a call to a JScript object, the bridge must be aware that it has to convert arguments according to the JScript requirements. Therefore, the bridge must know that one calls a JScript component, but the bridge is not capable of finding out what language was used. The programmer has to provide hints, by implementing a property with the name "_environment" that has the value "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;
 }

Assume there is a UNO object that implements the following interface function:

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

Now, call this function in JScript and provide a JScript implementation of XSimple:

 <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());
 ...

To build a component with C++, write the component from scratch or use a kind of framework, such as the Active Template Library (ATL). When a dual interface is used with ATL, the implementation of IDispatch is completely hidden and the functions must be implemented as if they were an ordinary custom interface, that is, use specific types as arguments instead of VARIANTs. If a UNO function has a return value, then it has to be specified as the first argument which is flagged as "retval".

 </script>
 // 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