OpenOffice C UNO Language Specification


Introduction


This document describes the C representation of UNO IDL types as generated by the cunomaker tool. Each C UNO type is generated into a corresponding .h header file and optional a .c source file if a special type function is wanted.
A getCUnoType_<full_qualified_typename>() function is available for each UNO type in the .h file if the special type function is generated. Calling this function you can obtain the meta type of a type, i.e. a value describing the type. Using this type (reference) you can get comprehensive description of the type using the C++ runtime (cppu library; have a look at typelib/typedescription.h).
The getCUnoType_<typename>() function has the following signature:


typelib_TypeDescriptionReference ** SAL_CALL getCUnoType_com_sun_star_uno_TypeClass();

The following sections define all types and UNO IDL constructs, which includes the binary memory layout, too.

Modules, Constants


An IDL module definition is mapped only in the name of an IDL type definition within the module. All IDL type definition within the module are mapped to their corresponding C type declarations with a full qualified type name.
IDL constant groups are mapped in the same way as modules. All defined constants in this constant group are mapped to static const variables with type, name and value of the IDL equivalent.

Example:


module foo
{
    constants group
    {
        const long BAR = 0xdb0;
    };
};

is generated to


file foo/bar.h:

static const sal_Int32 foo_group_BAR = (sal_Int32)0xdb0;

basic Types


The binary representation of UNO types is machine (e.g. big-/little-endian), language and operating system dependent. Alignment of data structures complicates even more, and is also processor and bus dependent. The alignment used for C UNO types is defined by the following algorithm:

Structure members are stored sequentially by the order they are declared. Every data object has an alignment-requirement. For structures, the requirement is the largest size of its members. Every object then has an allocated offset so that

offset % alignment-requirement == 0
If it is possible that the maximum alignment-requirement can be restricted (Microsoft C/C++ compiler, IBM C/C++ compiler using a compiler pragma), then it is set to 8. Under this condition the alignment-requirement is
alignment-requirement := min( 8, sizeof( type ) ).
struct-alignment-requirement := min( 8, sizeof( largest-member-type ) ).
The size of the struct is ceiled up to the largest integral member type.
In general, if the maximal alignment-requirement can be restricted to max-alignment, then it is
alignment-requirement := min( max-alignment, sizeof( type ) ).
struct-alignment-requirement := min( max-alignment, sizeof( largest-member-type ) ).
The size of the struct is ceiled up to the largest integral member type.

The following table shows the IDL type, size and layout of the basic C++ UNO specification. Only 32-Bit C++ UNO is specified and tested for now. Basic type definitions like sal_Int32 are defined in header sal/types.h.

IDL type

Size [byte]

C type

void

-

void

byte

1

signed 8 bit integer (sal_Int8)

short

2

signed 16 bit integer (sal_Int16)

unsigned short

2

unsigned 16 bit integer (sal_uInt16)

signed long

4

signed 32 bit integer (sal_Int32)

unsigned long

4

unsigned 32 bit integer (sal_uInt32)

hyper

8

signed 64 bit integer (sal_Int64)

unsigned hyper

8

unsigned 64 bit integer (sal_uInt64)

float

sizeof (float)

processor dependent: Intel, Sparc = IEEE float (float)

double

sizeof (double)

processor dependent: Intel, Sparc = IEEE double (double)

boolean

1

8 bit unsigned char (sal_Bool { 0, 1 })

char

2

16 bit unicode char (sal_Unicode)

string

4

struct rtl_uString * (header rtl/ustring.h)

type

4

struct typelib_TypeDescriptionReference * (header typelib/typedescription.h). A default constructed meta type refers to type VOID.

any

sizeof (uno_Any)

struct uno_Any (header uno/any2.h):

typedef struct _uno_Any
{
    typelib_TypeDescriptionReference * pType;
    void *                             pData;
} uno_Any;
The struct contains a pointer to the type and value that is held by the any. Anies cannot be nested, i.e. no any can contain an any!



Enum


An IDL enumeration is mapped to a C typedef to a C enumeration type (enum). The name of the enumeration is used as prefix for each enumeration label. The enumeration labels will be initialized with the defined values in IDL or by default in ascending order beginning with 0. The last label (EnumName_MAKE_FIXED_SIZE = SAL_MAX_ENUM) is appended to fix the size of the enumeration type to the compiler's sizeof(int).

Example:


module foo
{
    enum Bar
    {
        JOHN, DOE
    };
};

is generated to


file foo/Bar.h:



#ifdef __cplusplus
extern "C" {
#endif

typedef enum _foo_Bar
{
    foo_Bar_John = 0,
    foo_Bar_DOE = 1,
    foo_Bar_MAKE_FIXED_SIZE = SAL_MAX_ENUM
} foo_Bar;


#ifdef __cplusplus
}
#endif

Sequence


C UNO sequences are reference counted. The value type of a sequence is handled by a pointer to uno_Sequence which is of the following structure (headers uno/sequence2.h and sal/types.h):


typedef struct _sal_Sequence
{
    sal_Int32 nRefCount;
    sal_Int32 nElements;
    char      elements[1];
} sal_Sequence;

typedef sal_Sequence uno_Sequence;

Elements of the sequence follow up directly to the elements array. API functions to cope with sequences are in header uno/sequence2.h.

Sequences are used generically in UNO, i.e. nothing has to be generated for a specific sequence (e.g. used in an interface method declaration) by the cunomaker tool. A UNO IDL type usage of sequence< long > will last in a C UNO uno_Sequence *.

Array


XXX TODO: The array has yet to be specified, but is in work. Ask Juergen Schmidt for current status.
Thus the array specification is not fixed, to give an outlook: It will follow C array specification and generated to a C array of given element type. Arrays will allow multiple dimensions. In contrast to sequences C arrays are not reference counted, thus copying big arrays may be time consuming.

Interface


Interfaces are generated to C structs containing function pointers for each function. C interfaces are reference counted and are represented by an interface pointer.

Each function contains as first parameter a pointer to the implemented object itself and as second parameter (out parameter) a pointer to an uno_Any representing a possible thrown exception. Note that this parameter will not be valid if no exception occured. While return values are passed as pure out parameters (the third parameter if the function doesn't return void), each function returns a cuno_ErrorCode. This error code is used to signal if an exception was thrown or not.

The three different types of parameters are generated as follows:

  • in: the parameter is pure in parameter; it is passed as call-by-value for ordinal and float types or passed as pointer for complex types (e.g. structs, interfaces, sequences, strings).
  • out: the parameter is pure out parameter; it is anytime passed as pointer (e.g. base types, structs) or pointer pointer for reference counted types (e.g. interfaces, sequences, strings).
  • inout: the parameter is inout parameter; it is anytime passed as pointer or pointer pointer for reference counted types.

out parameters and return values are pure out paramters that means that you give only the memory for this types in the function but the types must not be constructed. If an exception occured these parameters are not valid.

  • a struct must be a pointer to the necessary memory
  • an interface must be a pointer to an interace pointer.

If the UNO IDL interface declares an attribute, the corresponding C struct gets an additional function pointer for getAttributeName() and setAttributeName() (if non-readonly).

Any interface method can declare exceptions that may be thrown upon invocation of it. Implicitly any method may throw com.sun.star.uno.RuntimeException (generated C struct com_sun_star_uno_RuntimeException). For exceptions using in C function an additional parameter (uno_Any *) is generted which transport the necessary exception information.
The latter said is valid except for com.sun.star.XInterface::acquire() and com.sun.star.XInterface::release() which never throw any exception.

Note: The queryInterface method will be changed in C. The return value specified in IDL of type any will be changed in the C type declaration to a pure out parameter of type com_sun_star_uno_XInterface pointer.


Interface inheritance is done by expanding the generated function table whith function pointers of all inherited functions. All interfaces inherit from UNO IDL interface com.sun.star.XInterface.

Example: com.sun.star.lang.XMultiServiceFactory


module com {  module sun {  module star {  module lang {

interface XMultiServiceFactory: com::sun::star::uno::XInterface
{ 
    com::sun::star::uno::XInterface createInstance(
        [in] string aServiceSpecifier ) 
        raises( com::sun::star::uno::Exception );
	
    com::sun::star::uno::XInterface createInstanceWithArguments(
        [in] string ServiceSpecifier, 
        [in] sequence Arguments ) 
        raises( com::sun::star::uno::Exception );
	
    sequence getAvailableServiceNames(); 
}; 

}; }; }; };

will be generated to (.h file)

#ifdef __cplusplus
extern "C" {
#endif

#ifndef COM_SUN_STAR_LANG_XMULTISERVICEFACTORY
#define COM_SUN_STAR_LANG_XMULTISERVICEFACTORY
struct _com_sun_star_lang_XMultiServiceFactory_ftab;
typedef struct _com_sun_star_lang_XMultiServiceFactory_ftab * com_sun_star_lang_XMultiServiceFactory;
#endif

typedef struct _com_sun_star_lang_XMultiServiceFactory_ftab
{
    /* Methods of com_sun_star_uno_XInterface */
    cuno_ErrorCode (SAL_CALL *queryInterface)( com_sun_star_uno_XInterface *, uno_Any *,
                                              com_sun_star_uno_XInterface **, typelib_TypeDescriptionReference * );
    cuno_ErrorCode (SAL_CALL *acquire)( com_sun_star_uno_XInterface * );
    cuno_ErrorCode (SAL_CALL *release)( com_sun_star_uno_XInterface * );

    /* Methods of com_sun_star_lang_XMultiServiceFactory */
    cuno_ErrorCode (SAL_CALL *createInstance)( com_sun_star_lang_XMultiServiceFactory *, uno_Any *,
                                              com_sun_star_uno_XInterface **, rtl_uString * );
    cuno_ErrorCode (SAL_CALL *createInstanceWithArguments)( com_sun_star_lang_XMultiServiceFactory *, uno_Any *,
                                                           com_sun_star_uno_XInterface **, rtl_uString *, 
                                                           /*sequence< any >*/ uno_Sequence * );
    cuno_ErrorCode (SAL_CALL *getAvailableServiceNames)( com_sun_star_lang_XMultiServiceFactory *, uno_Any *,
                                                        /*sequence< string >*/ uno_Sequence ** );
} com_sun_star_lang_XMultiServiceFactory_ftab;

#ifdef __cplusplus
}
#endif

Struct


UNO IDL Structs are generated to C typedefs to C structs declaring the C UNO types and members in the same order. The member names are identical. Struct inheritance is done by an additional member (the first member) with the inherited type. Note that the maximal alignment-requirement for structures for the OS/2 and Microsoft Visual C++ compiler is 8.

Example: com.sun.star.lang.Locale


module com {  module sun {  module star {  module lang {

struct Locale
{
    string Language;
    string Country;
    string Variant;
};

}; }; }; };

will be generated to (.h file)

#ifdef __cplusplus
extern "C" {
#endif

#ifdef SAL_W32
#   pragma pack(push, 8)
#elif defined(SAL_OS2)
#   pragma pack(8)
#endif

typedef struct _com_sun_star_lang_Locale
{
    rtl_uString * Language;
    rtl_uString * Country;
    rtl_uString * Variant;
} com_sun_star_lang_Locale;

#ifdef SAL_W32
#   pragma pack(pop)
#elif defined(SAL_OS2)
#   pragma pack()
#endif

#ifdef __cplusplus
}
#endif

Exception


Exceptions are generated similarly to structs, meaning they have identical binary layout. Exceptions are thrown by instance.
Exceptions need not inherit from any base exception, though UNO API conventions want any exception ([in-]directly) inherit from com.sun.star.uno.Exception.

Example: com.sun.star.lang.IllegalArgumentException


module com {  module sun {  module star {  module lang {  
 
exception IllegalArgumentException: com::sun::star::uno::Exception
{ 
    short ArgumentPosition; 
}; 
 
}; }; }; };  

will be generated to (.h file)

#ifdef __cplusplus
extern "C" {
#endif

#ifdef SAL_W32
#   pragma pack(push, 8)
#elif defined(SAL_OS2)
#   pragma pack(8)
#endif

typedef struct _com_sun_star_lang_IllegalArgumentException
{
    com_sun_star_uno_Exception _Base;
    sal_Int16 ArgumentPosition;
} com_sun_star_lang_IllegalArgumentException;

#ifdef SAL_W32
#   pragma pack(pop)
#elif defined(SAL_OS2)
#   pragma pack()
#endif

#ifdef __cplusplus
}
#endif

Union


XXX TODO: Currently, unions are not supported by the cunomaker tool, but nevertheless the runtime can cope with it. Union will be passed by a pointer. Unions will be generated as structs having a 64 bit discriminant as first member followed by a C union declaration. Alignment is as for structs.

Author: Jürgen Schmidt. Copyright 2001 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, CA 94303 USA.