Implementing UNO Language Bindings
- Implementing UNO Language Bindings
- UNO C++ Bridges
- UNO Reflection API
- XInvocation Bridge
This section introduces the basic steps to create a new language binding. The steps required depend on the target language. The section provides an overview of existing language bindings to help you to decide what is necessary for your case. It is recommended that you read the sources for available language bindings and transfer the solutions they offer to the new circumstances of your target language.
Overview of Language Bindings and Bridges
Creating a language binding for UNO involves the following tasks:
Language Specification and UNO Feature Support
When writing a language binding, consider how to map UNOIDL types to your target language, treat simple types and handle complex types, such as struct
, sequence
, interface
and any
. Furthermore, UNOIDL features, such as services, properties and exceptions must be matched to the capabilities of the target language and accommodated, if need be.
Code Generator
If the target language requires type definitions at compile time, a code generator must translate UNOIDL type definitions to the target language type definitions according to the language specification, so that the types defined in UNOIDL can be used.
UNO Bridge
UNO communication is based on calls to interfaces. Bridges supply the necessary means to use interfaces of UNO objects between implementation environments. The key for bridging is an intermediate environment called binary UNO,that consists of binary data formats for parameters and return values, and a C dispatch method used to call arbitrary operations on UNO interfaces. A bridge must be capable of the following tasks:
- Between the target language and Apache OpenOffice:
- Converting operation parameters from the target language to binary UNO.
- Transforming operation calls in the target language to calls in binary UNO in a different environment.
- Transporting the operation call with its parameters to Apache OpenOffice and the return values back to the target language.
- Mapping return values from binary UNO to the target language.
- Between Apache OpenOffice and the target language, that is, during callbacks or when using a component in the target language:
- Converting operation parameters from binary UNO to the target language.
- Transforming operation calls in binary UNO to calls in the target language.
- Transporting the operation call with its parameters to the target language and the return values back to Apache OpenOffice.
- Converting return values from the target language to binary UNO.
The Reflection API delivers information about UNO types and is used by bridges to support type conversions (com.sun.star.script.Converter), and method invocations (com.sun.star.script.Invocation and com.sun.star.script.XInvocation). Furthermore, it supplies runtime type information and creates instances of certain UNO types, such as structs (com.sun.star.reflection.CoreReflection).
UNO Component Loader
An implementation loader is required to load and activate code produced by the target language if implementations in the target language are to be instantiated. This involves locating the component files produced by the target language, and mechanisms to load and execute the code produced by the target language, such as launching a runtime environment. Currently, there are implementation loaders for jar files and locally shared libraries on the platforms supported by UNO.
Bootstrapping
A UNO language binding must prepare itself so that it can bridge to the UNO environments. It depends on the target environment how this is achieved. In Java, C++, and Python, a local service manager in the target environment is used to instantiate a com.sun.star.bridge.UnoUrlResolver that connects to Apache OpenOffice. In the Automation bridge, the object com.sun.star.ServiceManager
is obtained from the COM runtime system and in Apache OpenOffice Basic the service manager is available from a special method of the Basic runtime environment, getProcessServiceManager()
.
Implementation Options
There are two different approaches when creating a UNO language binding.
- Programming languages checking types at compile time. Examples are the languages Java or C++. In these environments, it is necessary to query for interfaces at certain objects and then invoke calls compile-time-typesafe on these interfaces.
- Programming languages checking types at runtime. Examples are the languages StarBasic, Python or Perl. In these languages, the interfaces are not queried explicitly as there is no compiler to check the signature of a certain method. Instead, methods are directly invoked on objects. During execution, the runtime engine checks if a method is available at one of the exported interfaces, and if not, a runtime error is raised. Typically, such a binding has a slight performance disadvantage compared to the solution above.
You can achieve different levels of integration with both types of language binding.
- Call existing UNO interfaces implemented in different bindings. This is the normal scripting use case, for example, connect to a remote running office, instantiate some services and invoke calls on these services (unidirectional binding).
- Implement UNO interfaces and let them be called from different bindings.In addition to 1) above, a language binding is able to implement UNO interfaces, for example, for instance listener interfaces, so that your code is notified of certain events (limited bidirectional binding).
- Implement a UNO component that is instantiated on demand from any other language at the global service manager. In addition to 2) above, a binding must provide the code which starts up the runtime engine of the target environment. For example, when a Java UNO component is instantiated by the Apache OpenOffice process, the Java VM must be loaded and initialized, before the actual component is loaded (bidirectional binding).
A language binding should always be bidirectional. That is, it should be possible to access UNO components implemented in the target language from Apache OpenOffice, as well as accessing UNO components that are implemented in a different language from the target language.
The following table provides an overview about the capabilities of the different language bindings currently available for Apache OpenOffice:
Language | scripting (accessing office objects) | interface implementation | component development |
---|---|---|---|
C++ (platform dependent) | yes | yes | yes |
Java | yes | yes | yes |
StarBasic | yes | (only listener interfaces) | no |
OLE automation (Win32 only) | yes | yes | no (maybe in the future) |
The next section outlines the implementation of a C++ language binding. The C++ binding itself is extremely platform and compiler dependent, which provides a barrier when porting Apache OpenOffice to a new platform. Although this chapter focuses on C++ topics, the chapter can be applied for other typesafe languages that store their code in a shared library, for instance, Delphi, because the same concepts apply.
The section UNO Reflection API considers the UNO reflection and invocation API, which offers generic functionality to inspect and call UNO objects. The section XInvocation Bridge explains how the Reflection API is used to implement a runtime type-checking language binding.
The final chapter Implementation Loader briefly describes the concept of implementation loaders that instantiates components on demand independently of the client and the implementation language. The integration of a new programming language into the UNO component framework is completed once you have a loader.
Content on this page is licensed under the Public Documentation License (PDL). |