Scripting Existing UNO Objects
This section describes UNO bridges for type-unsafe (scripting) programming languages. These bridges are based on the com.sun.star.script.Invocation service.
The most common starting point for a new scripting language binding is that you want to control Apache OpenOffice from a script running externally. To accomplish this, you need to know what your scripting language offers to extend the language, for example, Python or Perl extend the language with a module concept using locally shared libraries.
In general, your bridge must offer a static method that is called from a script. Within this method, bootstrap a UNO C++ component context as described in Bootstrapping a Service Manager.
Proxying a UNO Object
Next, this component context must be passed to the script programmer, so that you can instantiate a com.sun.star.bridge.UnoUrlResolver and connect to a running office within the script.
The component context can not be passed directly as a C++ UNO reference, because the scripting engine does not recognize it, therefore build a language dependent proxy object around the C++ object Reference.
For example, Python offers an API to create a proxy. Typically calls invoked on the proxy from a script are narrowed into one single C function. The Python runtime passes method names and an array containing the arguments to this C function.
If a proxy is implemented for a concrete interface, the method names that you received could in theory be compared to all method names offered by the UNO interface. This is not feasible, because of all the interfaces used in Apache OpenOffice. The com.sun.star.script.Invocation service exists for this purpose. It offers a simple interface com.sun.star.lang.XSingleServiceFactory that creates a proxy for an arbitrary UNO object using the
createInstanceWithArguments() method and passing the object the proxy acts for. Use the com.sun.star.script.XInvocation interface that is exported by this proxy to invoke a method on the UNO object.
In addition, argument conversion must be considered by specifying how each UNO type should be mapped to your target language.
Convert the language dependent data types to UNO data types before calling invoke() and convert the UNO datatypes (return value and out parameters) to language dependent types after the call has been exectuted. The conversion routines are typically recursive functions, because data values are nested in complex types, such as
When UNO object references are returned by method calls to UNO objects, create new language dependent proxies as discussed above. When passing a previously returned UNO object as a parameter to a new method call, the language binding must recognize that it is a proxied object and pass the original UNO object reference to the invoke() call instead.
A special case for conversions are UNOIDL structs. You want to call a method that takes a struct as an argument. The first problem is the struct must be created by the bridge and the script programmer must be able to set members at the struct. One solution is that the bridge implementer creates a UNO struct using core C functions from the
cppu library, but this is complicated and results in a lot of difficulty.
Therefore, a solution has been created that accesses structs through the
XInvocation interface, as if they were UNO objects. This simplifies struct handling for bridge programmers. Refer to the reference documentation of com.sun.star.reflection.CoreReflection and the com.sun.star.script.Invocation service and the com.sun.star.beans.XMaterialHolder interface.
UNO method calls may throw exceptions and must be mapped to the desired target language appropriately, depending on the capabilities of your target language. Ideally, the target language supports an exception concept, but error handlers, such as in OpenOffice.org Basic can be used also. A third way and worst case scenario is to check after every API call if an exception has been thrown,. In case the UNO object throws an exception, the
XInvocation proxy throws a com.sun.star.reflection.InvocationTargetException. The exception has an additional any member, that contains the exception that was really thrown.
Note that the
XInvocation proxy may throw a com.sun.star.script.CannotConvertException indicating that the arguments passed by the script programmer cannot be matched to the arguments of the desired function. For example, there are missing arguments or the types are incompatible. This must be reported as an error to the script programmer.
The com.sun.star.script.Invocation has special
setProperty() methods. These methods are used when the UNO object supports a property set and your target language, for example, supports something similar to the following:
object.propname = 'foo';.
Note that every property is also reachable by invoke
('setPropertyValue', ...), so these set or
getProperty functions are optional.
Implementing UNO objects
When it is possible to implement classes in your target language, consider offering support for implementation of UNO objects. This is useful for callbacks, for example, event listeners. Another typical use case is to provide a datasource through a com.sun.star.io.XInputStream.
The script programmer determines which UNOIDL types the developed class implements, such as flagged by a special member name, for example, such as
When an instance of a class is passed as an argument to a call on an external UNO object, the bridge code creates a new language dependent proxy that additionally supports the
XInvocation interface. The bridge code hands the
XInvocation reference of the bridge's proxy to the called object. This works as long as the invoke() method is used directly, for instance Apache OpenOffice Basic, except if the called object expects an
The com.sun.star.script.InvocationAdapterFactory service helps by creating a proxy for a certain object that implements
XInvocation and a set of interfaces, for example, given by the
__supportedUnoTypes variable. The proxy returned by the
createAdapater() method must be passed to the called object instead of the bridge's
XInvocation implementation. When the Adapter is queried for one of the supported types, an appropriate proxy supporting that interface is created.
If a UNO object invokes a call on the object, the bridge proxy's invoke() method is called. It converts the passed arguments from UNO types to language dependent types and conversely using the same routines you have for the other calling direction. Finally, it delegates the call to the implementation within the script.
It may become difficult if you do not want to start with an external scripting engine, but want to use the scripting engine inside the Apache OpenOffice process instead. This must be supported by the target language. Often it is possible to load some library dynamically and access the scripting runtime engine through a C API. It should be implemented as a UNO C++ component. There are currently no generic UNO interfaces for this case, except for the com.sun.star.loader.XImplementationLoader. Define your own interfaces that best match your requirements. You might instantiate from Basic and retrieve an initial object or start a script. Future versions of Apache OpenOffice may have a more comprehensive solution.
|Content on this page is licensed under the Public Documentation License (PDL).|