blob: e591e3128e6ab3aebb28f23f884edf144eadd734 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>
C++ UNO Language Specification
</TITLE>
<style type="text/css">
<!--
h1 { text-align:center; margin-top: 0.2cm; text-decoration: none; color: #ffffff; font-size: 6; margin-top: 0.2cm}
h2 { margin-top: 0.2cm; margin-bottom=0.1cm; color: #ffffff; background-color: #666699 }
li {margin-bottom: 0.2cm;}
dl {margin-bottom: 0.2cm;}
dd {margin-bottom: 0.2cm;}
dt {margin-bottom: 0.2cm;}
pre {background-color: #ffffcc;}
-->
</style>
</HEAD>
<body>
<TABLE WIDTH=100% BORDER=0 CELLPADDING=4 CELLSPACING=0 summary=header bgcolor=#666699>
<tr><td>
<h1> C++ UNO Language Specification </h1>
</td><td>
<A HREF="http://www.openoffice.org/">
<IMG SRC="../../../images/open_office_org_logo.gif" NAME="Grafik1" ALT="OpenOffice.org" ALIGN=RIGHT WIDTH=109 HEIGHT=54 BORDER=0/>
</A>
</TD></TR>
</TABLE>
<h2><A NAME="intro"></A> Introduction </h2>
<p>This document describes the C++ representation of UNO IDL types as generated by the
<a href="../../../common/man/tools.html#cppumaker"><code>cppumaker</code> tool</a>.
Each C++ UNO type is generated into a corresponding <code>hpp</code> and
<code>hdl</code> header file. The <code>hdl</code> file contains only declarations while
the <code>hpp</code> includes it and defines all inline functions (e.g., default
constructors).</p>
<p>A inline <code>getCppuType()</code> function is available for each UNO type either
in a <code>hpp</code> file or from basic type headers
(, e.g. <code>com/sun/star/uno/Any.hxx</code>).</p>
<p>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 (<code>cppu</code> library; have a look at
<code>typelib/typedescription.h</code>).</p>
<p>The <code>getCppuType()</code> function has the following signature to be used for
template statements:</p>
<pre>
// global lnamespace implied
const ::com::sun::star::uno::Type &amp; SAL_CALL getCppuType( const <i>Type</i> * );
</pre>
<p>The UNO IDL character <code>char</code> type which is defined to be a C++
<code>sal_Unicode</code> 16 bit unsigned short integer is ambiguous to the C++
UNO IDL unsigned short (<code>sal_uInt16</code>), thus this points out an exception
to the rule above. Also, the <code>void</code> type cannot be used, because any C++ pointer
can be implicitly casted to a <code>void</code> pointer.</p>
<pre>
// global namespace implied
// header com/sun/star/uno/Type.hxx
const ::com::sun::star::uno::Type &amp; SAL_CALL getCppuCharType();
const ::com::sun::star::uno::Type &amp; SAL_CALL getCppuVoidType();
// header com/sun/star/uno/Sequence.hxx
const ::com::sun::star::uno::Type &amp; SAL_CALL getCharSequenceCppuType();
</pre>
<p>The following sections define all types and UNO IDL constructs,
which includes the binary memory layout, too.</p>
<ul>
<li><a href="#modules">Modules, Constants</A></li>
<li><a href="#basic_types">basic Types</A></li>
<li><a href="#enum">Enum</A></li>
<li><a href="#sequence">Sequence</A></li>
<li><a href="#array">Array</A>
<li><a href="#interface">Interface</A></li>
<li><a href="#struct">Struct</A></li>
<li><a href="#exception">Exception</A></li>
<li><a href="#union">union</A></li>
</ul>
<h2><A NAME="modules"></A> Modules, Constants </h2>
<p>An IDL module definition is mapped to a C++ namespace with the same name.
All IDL type definition within the module are mapped to their corresponding C++ type
declarations within the generated namespace.
IDL declarations which are not enclosed in any modules are mapped into the C++ global scope.</p>
<p>IDL constant groups are mapped to a C++ namespaces with the same name as the constant group.
All defined constants in this constant group are mapped to static const variables with type,
name and value of the IDL equivalent.</p>
<p>
Example:
<pre>
module foo
{
constants group
{
const long BAR = 0xdb0;
};
};
</pre>
<p>is generated to</p>
<pre>
file foo/bar.hdl:
namespace foo
{
namespace group
{
static const sal_Int32 BAR = (sal_Int32)0xdb0;
}
}
</pre>
<h2><A NAME="basic_types"></A> basic Types </h2>
<p>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:</p>
<p>
Structure members are stored sequentially by the order they are declared.
Every data object has an <i>alignment-requirement</i>.
For structures, the requirement is the largest size of its members.
Every object then has an allocated <i>offset</i> so that</p>
<pre>
<i>offset</i> % <i>alignment-requirement</i> == 0
</pre>
<p>If it is possible that the maximum <code>alignment-requirement</code> 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</p>
<pre>
alignment-requirement := min( 8, sizeof( <i>type</i> ) ).
struct-alignment-requirement := min( 8, sizeof( <i>largest-member-type</i> ) ).
</pre>
<p>The size of the struct is ceiled up to the largest integral member type.</p>
<p>In general, if the maximal <code>alignment-requirement</code> can be restricted to <i>max-alignment</i>,
then it is</p>
<pre>
alignment-requirement := min( <i>max-alignment</i>, sizeof( <i>type</i> ) ).
struct-alignment-requirement := min( <i>max-alignment</i>, sizeof( <i>largest-member-type</i> ) ).
</pre>
<p>The size of the struct is ceiled up to the largest integral member type.</p>
<p>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 <code>sal_Int32</code> are defined in header
<code>sal/types.h</code>.</p>
<TABLE WIDTH=904 BORDER=1 CELLPADDING=5 CELLSPACING=0>
<COL WIDTH=128> <COL WIDTH=98> <COL WIDTH=318> <THEAD>
<tr>
<th>IDL type</th>
<th>Size [byte]</th>
<th>C++ type</th>
</TR>
</THEAD><TBODY>
<tr>
<td><code>void</code></td>
<td><code>-</code></td>
<td>void</td>
</TR>
<tr>
<td><code>byte</code></td>
<td><code>1</code></td>
<td>signed 8 bit integer (<code>sal_Int8</code>)</td>
</TR>
<tr>
<td><code>short</code></td>
<td><code>2</code></td>
<td>signed 16 bit integer (<code>sal_Int16</code>)</td>
</TR>
<tr>
<td><code>unsigned short</code></td>
<td><code>2</code></td>
<td>unsigned 16 bit integer (<code>sal_uInt16</code>)</td>
</TR>
<tr>
<td><code>signed long</code></td>
<td><code>4</code></td>
<td>signed 32 bit integer (<code>sal_Int32</code>)</td>
</TR>
<tr>
<td><code>unsigned long</code></td>
<td><code>4</code></td>
<td>unsigned 32 bit integer (<code>sal_uInt32</code>)</td>
</TR>
<tr>
<td><code>hyper</code></td>
<td><code>8</code></td>
<td>signed 64 bit integer (<code>sal_Int64</code>)</td>
</TR>
<tr>
<td><code>unsigned hyper</code></td>
<td><code>8</code></td>
<td>unsigned 64 bit integer (<code>sal_uInt64</code>)</td>
</TR>
<tr>
<td><code>enum</code></td>
<td><code>4</code></td>
<td>C++ enum</td>
</TR>
<tr>
<td><code>float</code></td>
<td><code>sizeof (float)</code></td>
<td>processor dependent: Intel, Sparc = IEEE float (<code>float</code>)</td>
</TR>
<tr>
<td><code>double</code></td>
<td><code>sizeof (double)</code></td>
<td>processor dependent: Intel, Sparc = IEEE double (<code>double</code>)</td>
</TR>
<tr>
<td><code>boolean</code></td>
<td><code>1</code></td>
<td>8 bit unsigned char (<code>sal_Bool { 0, 1 }</code>)</td>
</TR>
<tr>
<td><code>char</code></td>
<td><code>2</code></td>
<td>16 bit Unicode char (<code>sal_Unicode</code>)</td>
</TR>
<tr>
<td><code>string</code></td>
<td><code>4</code></td>
<td>Wrapper class <code>::rtl::OUString</code>
(header <code>rtl/ustring</code>) acquiring reference
to struct <code>rtl_uString</code> (header <code>rtl/ustring.h</code>).
</td>
</TR>
<tr>
<td><code>type</code></TD>
<td><code>4</code></TD>
<td>Wrapper class <code>::com::sun::star::uno::Type</code> acquiring
reference to <code>typelib_TypeDescriptionReference</code>
(header <code>typelib/typedescription.h</code>).
A default constructed meta type refers to type <code>VOID</code>.
</td>
</TR>
<tr>
<td><code>any</code></TD>
<td><code>sizeof (uno_Any)</code></TD>
<td>Wrapper class <code>::com::sun::star::uno::Any</code>
(header <code>com/sun/star/uno/Any.hxx</code>) derived from
struct <code>uno_Any</code> (header <code>uno/any2.h</code>):
<pre>
typedef struct _uno_Any
{
typelib_TypeDescriptionReference * pType;
void * pData;
} uno_Any;
</pre>
<p>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!
</p>
</TD></TR>
</TBODY></TABLE>
<h2><A NAME="enum"></A> Enum </h2>
<p>An IDL enumeration is mapped to a C++ enumeration type (<code>enum</code>).
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 (<i>EnumName</i><code>_MAKE_FIXED_SIZE = SAL_MAX_ENUM</code>)
is appended to fix the size of the enumeration type to 32 bit.
<p>
Example:
<pre>
module foo
{
enum Bar
{
JOHN, DOE
};
};
</pre>
<p>is generated to</p>
<pre>
file foo/Bar.hdl:
namespace foo
{
enum Bar
{
Bar_John = 0,
Bar_DOE = 1,
Bar_MAKE_FIXED_SIZE = SAL_MAX_ENUM
};
}
</pre>
<h2><A NAME="sequence"></A> Sequence </h2>
<p>C++ UNO sequences are reference counted. The value type of a sequence is handled by
template class <code>::com::sun::star::uno::Sequence</code>
(header <code>com/sun/star/uno/Sequence.hxx</code>).
It acquires a pointer to <code>uno_Sequence</code> which is of the following
structure (headers <code>uno/sequence2.h</code> and <code>sal/types.h</code>):
<pre>
typedef struct _sal_Sequence
{
sal_Int32 nRefCount;
sal_Int32 nElements;
char elements[1];
} sal_Sequence;
typedef sal_Sequence uno_Sequence;
</pre>
<p>Elements of the sequence follow up directly to the elements array.
API functions to cope with sequences are in header <code>uno/sequence2.h</code>.
<p>
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
<a href="../../../common/man/tools.html#cppumaker"><code>cppumaker</code> tool</a>.
A UNO IDL type usage of <code>sequence< long ></code> will last in a C++ UNO
<code>::com::sun::star::uno::Sequence< sal_Int32 ></code>.
<p>Header <code>com/sun/star/uno/Sequence.hxx</code> defines a template
<code>getCppuType()</code>
function (template parameter is C++ UNO element type).
As stated in the first section, UNO IDL type <code>char</code> is ambiguous to
<code>unsigned short</code> C++ UNO type.
Thus for UNO IDL <code>sequence< char ></code> you
have to use <code>getCharSequenceCppuType()</code> obtaining its meta type
(header <code>com/sun/star/uno/Sequence.hxx</code>).
<h2><A NAME="array"></A> Array </h2>
<p>
XXX TODO:
The array has yet to be specified, but is in work.
Ask <a href="mailto:Juergen.Schmidt@germany.sun.com">Juergen Schmidt</a>
for current status.
<p>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 <a href="#sequence">sequences</a> C arrays are <b>not</b> reference
counted, thus copying big arrays may be time consuming.
<h2><A NAME="interface"></A> Interface </h2>
<p>
Interfaces are generated to C++ classes having pure virtual member functions
(, e.g. <code>virtual void foo() = 0</code>).
C++ interface references control the lifetime of an interface
(template wrapper class <code>::com::sun::star::uno::Reference<></code>
in header <code>com/sun/star/uno/Reference.hxx</code>) and hold the acquired
interface pointer as only member.
They build up the value type of an interface, i.e. if a method expects an interface,
this implicitly means it gets an interface reference.
Note that the generated <code>getCppuType()</code> generated in the <code>hpp</code>
file has the following signature:
<pre>
inline const ::com::sun::star::uno::Type& SAL_CALL getCppuType(
const ::com::sun::star::uno::Reference< <i>generated_C++_class</i> >* )
throw();
</pre>
<p>
Return values are passed as C++ return values, the three different
types of parameters are generated as follows:
<ul>
<li><i>in</i>: the parameter is pure in parameter; it is passed as call-by-value for
ordinal and float types or passed as call-by-reference
(<code>const &amp;</code> [const C++ reference]) for C++ objects (, e.g. struct, exception, interface
reference).
</li>
<li><i>out</i>: the parameter is pure out parameter; it is anytime passed as call-by-reference
(<code>&amp;</code> [non-const C++ reference]).
</li>
<li><i>inout</i>: the parameter is inout parameter; it is anytime passed as call-by-reference
(<code>&amp;</code> [non-const C++ reference]).
</li>
</ul>
</p>
<p>If the UNO IDL interface declares an attribute, the corresponding C++ class gets a
<code>get</code><i>AttributeName</i><code>()</code> and
<code>set</code><i>AttributeName</i><code>()</code>
(if non-<code>readonly</code>).
<p>Any interface method can declare <a href="#exception">exceptions</a>
that may be thrown upon invocation of it.
Implicitly any method may throw <code>com.sun.star.uno.RuntimeException</code>
(generated C++ struct <code>::com::sun::star::uno::RuntimeException</code>).
For now exception clauses are generated for the pure virtual member functions, but
due to compiler bugs this heavily increases code size on some platforms.
So the currently used C++ <code>throw</code> clause will probably exchanged by a macro
expansion soon. But nevertheless this only affects exception declarations, C++ UNO exceptions
can be thrown and caught as common in C++ (<code>try ... catch ()</code>).</p>
<p>The latter said is valid except for <code>com.sun.star.XInterface::acquire()</code>
and <code>com.sun.star.XInterface::release()</code> which never throw any exception.
<p>Interface inheritance is similarly adopted to C++ class inheritance.
All interfaces inherit from UNO IDL interface <code>com.sun.star.XInterface</code>
(i.e. C++ generated class <code>::com::sun::star::XInterface</code>)
which serves as a base for lifetime control and querying the object for interfaces.
<p>
Example: <code>com.sun.star.lang.XMultiServiceFactory</code>
<pre>
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<any> Arguments )
raises( com::sun::star::uno::Exception );
sequence<string> getAvailableServiceNames();
};
}; }; }; };
</pre>
<p>will be generated to (<code>hdl</code> file)</p>
<pre>
namespace com
{
namespace sun
{
namespace star
{
namespace lang
{
class XMultiServiceFactory : public ::com::sun::star::uno::XInterface
{
public:
virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
createInstance( const ::rtl::OUString&amp; aServiceSpecifier )
throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) = 0;
virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
createInstanceWithArguments(
const ::rtl::OUString&amp; ServiceSpecifier,
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >&amp; Arguments )
throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) = 0;
virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
getAvailableServiceNames( )
throw(::com::sun::star::uno::RuntimeException) = 0;
};
} // lang
} // star
} // sun
} // com
</pre>
<p>Oneway declarations are ignored for C++ bridges, they only affect inter-process bridges.
The macro <code>SAL_CALL</code> forces C calling convention to be used, e.g.
<code>__cdecl</code> for the Microsoft Visual C++ compiler.
<h2><A NAME="struct"></A> Struct </h2>
<p>UNO IDL Structs are generated to C++ structs declaring the C++ UNO types and members
in the same order. The member names are identical.
A default constructor initializing all members to their default values is generated, too.
Struct inheritance is adopted to C++ inheritance.
Note that the maximal alignment-requirement for structures for the OS/2 and Microsoft Visual C++
compiler is 8.
<p>
Example: <code>com.sun.star.lang.Locale</code>
<pre>
module com { module sun { module star { module lang {
struct Locale
{
string Language;
string Country;
string Variant;
};
}; }; }; };
</pre>
<p>will be generated to (<code>hdl</code> file)</p>
<pre>
namespace com
{
namespace sun
{
namespace star
{
namespace lang
{
#ifdef SAL_W32
# pragma pack(push, 8)
#elif defined(SAL_OS2)
# pragma pack(8)
#endif
struct Locale
{
inline Locale();
// inline ctor definition in hpp file
inline Locale(
const ::rtl::OUString&amp; __Language,
const ::rtl::OUString&amp; __Country,
const ::rtl::OUString&amp; __Variant );
::rtl::OUString Language;
::rtl::OUString Country;
::rtl::OUString Variant;
};
#ifdef SAL_W32
# pragma pack(pop)
#elif defined(SAL_OS2)
# pragma pack()
#endif
} // lang
} // star
} // sun
} // com
</pre>
<h2><A NAME="exception"></A> Exception </h2>
<p>Exceptions are generated similarly to <a href="#struct">structs</a>, meaning
they have identical
binary layout. There is only one minor difference in generation, i.e. exceptions are declared as
C++ classes not as structs. Exception members appear in the <code>public</code> section
of the class. Exceptions are thrown by instance.
<p>
Exceptions need not inherit from any base exception, though UNO API conventions
want any exception ([in-]directly) inherit from <code>com.sun.star.uno.Exception</code>.
<p>
Example: <code>com.sun.star.lang.IllegalArgumentException</code>
<pre>
module com { module sun { module star { module lang {
exception IllegalArgumentException: com::sun::star::uno::Exception
{
short ArgumentPosition;
};
}; }; }; };
</pre>
<p>will be generated to (<code>hdl</code> file)</p>
<pre>
namespace com
{
namespace sun
{
namespace star
{
namespace lang
{
class IllegalArgumentException : public ::com::sun::star::uno::Exception
{
public:
// inline ctor definition in hpp file
inline IllegalArgumentException();
// inline ctor definition in hpp file
inline IllegalArgumentException(
const ::rtl::OUString&amp; __Message,
const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&amp; __Context,
const sal_Int16&amp; __ArgumentPosition );
sal_Int16 ArgumentPosition;
};
} // lang
} // star
} // sun
} // com
</pre>
<h2><A NAME="union"></A> Union </h2>
<p>
XXX TODO:
Currently, unions are not supported by the
<a href="../../../common/man/tools.html#cppumaker"><code>cppumaker</code> tool</a>,
but nevertheless the runtime can cope with it.
Union will be passed by C++ reference upon member function calls except for return values.
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.
<table bgcolor=#666699 summary=footer width=100%>
<TR><td>
<FONT COLOR="#ffffff">
Author: <A HREF="mailto:Daniel.Boelzle@germany.sun.com">
<FONT COLOR="#ffffff">Daniel B&ouml;lzle</A>. Last modified $Date: 2004/12/08 12:41:09 $<br/>
<I>Copyright 2001 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, CA 94303 USA.</I>
</FONT>
</TD></tr>
</TABLE>
</BODY>
</html>