Uno/Article/Understanding Uno

From Apache OpenOffice Wiki
< Uno
Revision as of 08:41, 20 August 2006 by Cedricbosdo (Talk | contribs)

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

This article is intended at explaining the basic concepts of UNO to newcomers. This document has nothing to teach to persons already programming using UNO. After reading these pages, the reader should be able to understand most of the programming documents including the IDL reference.

However this document does not aim at replacing nor simplifying the Developer's Guide chapters about UNO: it is only a list of some interesting points to start with. This paper is not a tutorial to develop a UNO component: this has already been done in other documents.

Introduction, what is UNO ?

"UNO, why do I need to know what it is ?" would be the first question to ask when reading this paper. In fact, UNO is the component model: thus understanding its basic concepts is very important to start programming on

Brief UNO overview

As stated above, UNO is the central concept in because it manages all the internal objects. To make it simple, UNO provides a way to call other objects without taking care of their implementation language or their execution environment. In fact a method call in OOoBasic is translated into a UNO call to the right implementation method. An other feature of UNO is to allow external programs to get running objects using a network connection.

Considering all these UNO capabilities, understanding it is important to develop new UNO components, but even to use API in macros or external programs. Even if this article is very component developer oriented, it is often useful to have this point of view to use components. This article is composed of a first section introducing the main concepts and a second section presenting their impacts on components development.

Strange terms and abbreviations used

This section will be useful for those who are not familiar with some development terms. However, all these definitions are important for a correct understanding of this article. They can even be used as a reference for further reading.

  • API (Application Programming Interface): a set of methods and attributes available for use in other programs or components. API is also known as IDL Reference.
  • Binding: for programming, a binding is a translation of IDL specifications into a given programming language. A binding includes although some language-dependent methods and helpers to handle UNO concepts.
  • Bridge: this concept is tightly bound to the binding notion. A bridge for UNO is a piece of code which allows a binding to a language. Developing a bridge implies to have a good knowledge of UNO and all its mechanisms.
  • Component: a component is a block providing features described by its specifications. A best practice is to try to keep the components as independent as possible.
  • IDL (Interface Description Language): common specification description language. This language is used to describe the types defined by a component. This language is converted in a language-specific way, depending on the used binding. The specification files generally has the ".idl" extension.
  • Registry: a binary file containing all the compiled specifications of a component. There are two types of registries: types registries which contains the UNO types definitions and services registries linking the specification to the implementation. This file generally has the ".rdb" extension.
  • SDK (Software Development Kit): is a set of tools and definition files to develop on a program. SDK is provided on the download page.
  • Specification: the description of what the code should do. In UNO, this contains the documentation shown in the reference.
  • UNO (Universal Network Objects): the component model. This will be more detailed in this article.
  • URE (UNO Runtime Environment): a subset of allowing to develop other UNO-based applications. It can be downloaded on the download page.

UNO basics

This section will present the main ideas of UNO which make programming with it different than other traditional programming. This section will follow the steps of a component's development, however it cannot be considered as a tutorial.

Specification and Implementation

First things firsts, making the distinction between specification and implementation is important. Even if these notions are present in most of the applications, they have a particular meaning for UNO. In normal applications, the specifications are defined in some documents in natural language. This exists in and is also called "specifications", but UNO specifications are different.

Specifications in UNO is a set of methods and properties defining an API. They are written in a common programming language called IDL. They define the different types available from other UNO code.

In order for the component to be complete, it has to contain an implementation of its UNO specifications. This implementation could be written in any of the languages supported by UNO. To make a language available for UNO, a bridge between this language and UNO has to be created. The most common implementation languages are C++, Java and Python, but others are available. For more information on the supported languages, please report to the UDK project page or the Uno wiki page.

As shown by the previous illustration, a component's method call will return to the UNO Runtime Environment. This one will translate the call into an implementation call using the services registries. This illustration doesn't reflect the real UNO component composition. It normally contains:

 *a type registry, representing the specification in a binary file
 *the implementation usually delivered as a shared library
 *the services registry describing the mapping between the specified types and their implementations.

As explained later, the services registry will impose some more constraints on the component development. The component build process will not be explained here, but is detailed in the Java component tutorial.

IDL first approach

In order to understand most of the documents, a new developer has to be used to UNO-IDL main notions. The main types in UNO-IDL are services and interfaces. An interface defines a set of methods and attributes whereas a service exports an interface.

As every Object Oriented language, IDL supports inheritance. However, services - which can often be compared to Objects in other languages - do not support multiple inheritance: only the interfaces do. This is a new feature of UNO coming with 2.0, but IDL still allows a service to export more than one interface: this has been kept for backward compatibility. Thus the API still contains some of these services.

The following snippet is the IDL specification of a simple bank account service. This bank account has balance, maximum and rate attributes.

module org { module openoffice { module bank {
    interface XBankAccount {
        [attribute] short Balance;
        [attribute] short Maximum;
        [attribute] double Rate {
            set StupidRateException;

        short giveAmount([in] short iAmount);
        short receiveAmount([in] short iAmount);

    exception StupidRateException {
        short MaxRate;
        short MinRate;
        short WantedRate;

    service BankAccount: XBankAccount {
        create(short iBalance, short iMaximum, double dRate);
}; }; };

This specification shows some well-known notions as exceptions, and interfaces. Somewhat this example doesn't show is the specification documentation: the IDL reference is generated from javadoc-like comments in these files.

Remote objects

The last important UNO concept that will be explained here is the one of proxy objects. In fact UNO doesn't let client code handle the object instance directly: it creates proxy object in order to establish a bridge between the implementation language and the client code language. This notion can be found in other networking object systems like Corba or ICE.

This principle is illustrated by the above illustration. In fact the object instance is created only once and then proxies are created to access this instance. This way the proxy can be in another language or another UNO Runtime Environment than the real object. However, for a developer, this concept is quite transparent. In some language bindings there are methods like queryInterface() which seem difficult to understand((When I started to understand UNO, this createInterface() was used everywhere in the developer's guide first chapters, but I only understood its use when I studied Corba and the remote objects. As stated in this document, this mechanism will tend to disappear from UNO and is kept for backwards compatibility.)).

With the last version of UNO coming with 2.0, these methods have become useless. In fact, these queryInterface() methods were used to fetch one specific interface of a service. Now that a service can export only one interface, this becomes useless because creating the service returns necessarily the right interface reference.

Impacts on programming

This paper doesn't aim at describing the exact steps to create a component. This chapter will only explain some UNO impacts on the implementation. In the next sections, the first one on the language bindings can be useful for every UNO or OOo programmer. However the two other parts are written for UNO components developers.

Language bindings

As stated previously, UNO can be used with many languages. This is possible thanks to UNO bridges and has some impacts on programming. From a UNO user point of view, a binding provides several important things:

  • A mapping between UNO and the language types. This includes simple types and complex ones like services, interfaces or singletons.
  • Tools to generate code from the IDL specifications. In order to be used in the programming language, the IDL specifications have to be translated. For Java and C++, this can be respectively done by using the javamaker and cppumaker tools.
  • A set of helper methods and objects, often for component implementation.
  • A binding documentation in order to understand its specific notions.

Using a binding is not necessarily simple and it may vary with the languages. For example, the OOoBasic binding is very easy to understand: one of the only difficult things is the difference between the Variant and Object types. The most important bindings documentation is contained in the developer's guide, but others are available on the UDK project home page or on the Uno wiki page.

Registration methods

In order to bind the specifications to their implementation, components contains a services.rdb registry. To create this file, there are some methods to add in the component implementation: these are called "Registration methods". Each binding has its own set of registration methods to implement, but the idea is always the same: they return a mapping between the UNO type name and its implementation name.

To know exactly what is to be implemented for the component language, please report to the binding documentation. Afterwards, the services.rdb file is generated by running the regcomp tool against the component library.

The XTypeProvider interface

It is important to read the next lines to let the component be handled by OOoBasic. This language doesn't use the same mechanisms to find a method or property in a service. is an IDL interface provided with and the URE. To have OOoBasic support, this interface has to be implemented by the component, otherwise the following problems could appear:

 *the methods Dbg_Properties, Dbg_Methods and Dbg_SupportedInterfaces will return nothing
 *using a method or property of the service will raise an unknown member error.

In fact OOoBasic uses the XTypeProvider interface to find the properties and methods of a service. The same problems can occur when the XTypeProvider is implemented using the wrong types. This latter error seems very odd, but can come very easily when using helpers to implement the XTypeProvider interface in complex designs. For example, consider the following IDL specification:

module org { module openoffice { module test {

    interface XA {
        [attribute] string name;

    interface XB: XA {
        [attribute] short value;

    service A: XA;
    service B: XB;

}; }; };

The implementation could define a helper to implement A and B common parts. However, if this helper uses a helper to implement XTypeProvider, both A and B services could have the same XTypeProvider implementation if this was not properly done. Thus the following OOoBasic code will fail because the XB properties and attributes are not defined using the XTypeProvider.

someB.value = 2;
Personal tools