IDL Files and Cpp
For an introduction, you can read tutorial.
Contents
Services and Interfaces
Introduction
See tutorial (in pdf) chapter 2 In OpenOffice API, a "service" is an abstract concept providing certain interfaces and properties/attributes. As Developer's Guide states : “Properties are data in an object that are provided by name over a generic interface for property access, that contains getPropertyValue() and setPropertyValue() access methods.”. It would be better to distinguish between attribute and property. A service has a collection of properties and an interface is a collection of methods that provide a means to change properties.
Danny Brewer's rules
Services are similar to objects in java.
1. A service can inherit from zero or one other service. (which each service can recursively follow these rules.) 2. A service can include zero or more services. (which each service can recursively follow these rules.) 3. A service can export (implement) interfaces. 4. A service can have properties.
5. An interface can inherit from zero or one other interface. (which each interface can recursively follow these rules.) 6. An interface can include from zero or more interfaces. (which each interface can recursively apply these rules.) 7. An interface can implement methods. 8. An interface is always named with an X.
From these rules you can deduce that methods are ALWAYS found in interfaces, and properties are ALWAYS found in services.
IDL specification
Interfaces are specified using an Interface definition language (IDL). UNO uses UNO-IDL as the interface definition language. The Interface Definition Language (IDL) is a descriptive language (not a programming language) to describe the interfaces being implemented by the objects. Within IDL, you define the name of the interface, the names of each of the attributes and methods, and so forth. Once you've created the IDL file, you can use an IDL compiler to generate the header files in the C++ programming language. The way to specify simple modules with IDL is so straightforward that we choose to give only examples at first.
Specifying an interface
We choose as an example, the interface XdrivingDirection (not in OOo):
// IDL interface XdrivingDirection { void turnLeft(); void turnRight(); };
Specifying a service
Example above is still used, here is the corresponding IDL specification :
// IDL interface XdrivingDirection { void turnLeft(); void turnRight(); }; interface XaccelerationControl { void speedUp(); void slowDown(); }; service car { // exported interfaces: interface XdrivingDirection; interface XaccelerationControl; [attribute] float speed; [attribute] float angle; };
We see a float type and we would use other IDL types later.
Specifying a module
Now, the same example would give this IDL specification :
// IDL module my_module { interface Xsomething { void methodone(); }; service my_service1 { // exported interfaces: interface Xsomething; }; interface XsomethingElse { void methodTwo(); void methodThree(); }; service my_service2 { // exported interfaces: interface XsomethingElse; }; };
Further with IDL
The IDL's types are :
char |
16-bit unicode character type |
boolean |
boolean type; true and false |
byte |
8-bit ordinal integer type |
short |
signed 16-bit ordinal integer type |
unsigned short |
unsigned 16-bit ordinal integer type |
long |
signed 32-bit ordinal integer type |
unsigned long |
unsigned 32-bit integer type |
hyper |
signed 64-bit ordinal integer type |
unsigned hyper |
unsigned 64-bit ordinal integer type |
float |
processor dependent float |
double |
processor dependent double |
string |
string of 16-bit unicode characters |
any |
universal type, takes every fundamental or compound UNO type, similar to Variant in other environments or Object in Java |
void |
Indicates that a method does not provide a return value |
Methods can have arguments. Each argument in the argument list must begin with one of the direction flags [ in ] , [ out ] or [ inout ] before a known type and identifier for the argument is given. We give an example that we will often encounter in this document : the counter example
An interface can be derived from a base interface. A derived interface can declare its own attributes and methods. Attributes and methods cannot be redefined in the derived interface. An example of interface inheritance :
//IDL interface animal { attribute long age; }; interface dog : animal { attribute short leg; }
Multiple inheritance is also possible :
// IDL interface dog : animal, friend {
Inheritance in service is presented in the next chapter.
In the OOo object terminology there is a difference between attribute and property. The only difference is how to access them. Properties are accessed with setPropertyValue(PropertyName,Any) whereas attributes are accessed with set/get(AttributeName) methods. We have already encounter properties manipulation when examining shapes.
Gathering UNO information with IDL files
There are several ways to find information on UNO.
One way is to use OooBasic and Bernard Marcelly's Xray tool (available here). Problem : OooBasic doesn't show exact methods and properties.
An other way is to use web service at : General OOoWEB Index
We have provided examples in previous chapters (particularly programming OOoWriter in C++) and then normally reader has skills on the subject.
IDL and C++
This problem is tackled in Developer's guide
Getting an interface in C++
In C++, you only have variables of an Interface type.
One of the most often encountered problem in C++ programming is querying an interface. This problem occurs very rarely in OooBasic but very often in C++/Java. We can find an example in chapter 2 and many other in chapter 3. As an example, we suppose we have to get a com::sun::star::document::officeDocument service. This is done in general by something like:
[cpp]
//Listing 2 C++ code to get a service
//C++
Reference<com::sun::star::document::officeDocument> OfDoc = something_to_get_this_service();
or
[cpp]
Listing 3 using namespace to simplify the code
//C++
using namespace com::sun::star::document;
....
Reference<officeDocument> OfDoc = something_to_get_this_service();
and we want to query the XStorable interface to save our document. Three steps are involved in this query :
- Add your code's line as UNO's query
[cpp]
//Listing 4 The UNO query in C++ code
// C++
// query from com::sun::star::frame::XStorable interface
Reference< XStorable > oToStore (OfDoc, UNO_QUERY);
- Add the hpp file in an include statement. Add the corresponding namespace in an using namespace statement. Including is done with :
[cpp]
//Listing 5 The corresponding include statement
//C++
#include <com/sun/star/frame/XStorable.hpp>
and the corresponding namespace statement is :
[cpp]
//Listing 6 The corresponding namespace statement
//C++
using namespace com::sun::star::frame;
- Add the corresponding type in the makefile as shown below in red :
# makefile # added com.sun.star.frame.XStorable TYPES := \ com.sun.star.uno.XNamingService \ .... com.sun.star.uno.XAggregation \ com.sun.star.frame.XStorable \ com.sun.star.lang.XMain \ ... com.sun.star.container.XHierarchicalNameAccess
Learn to realize these three steps : you can not program in C++ without encountering an interface's query. This problem of asking an interface is already tackled in chapters 3 and 4. An other more technical problem is the mapping : you have an IDL file, how is it compiled in C++ ? The next chapter tackle the subject : you can skip it in a first reading and go on into the chapter 1.5.
Mapping for Modules and Interfaces
For instance:
// IDL module M { struct E { long L; }; };
is mapped into:
[cpp]
// C++
namespace M
{ struct E
{ Long L; };
}
and E can be referred outside of M as M::E. Alternatively, a C++ using statement for namespace M can be used so that E can be referred to simply as E:
[cpp]
// C++
using namespace M;
E e;
e.L = 3;
Core reflection service and its Interfaces
XIdlReflection interface
Developer's Guide : The service com.sun.star.reflection.CoreReflection supporting the interface com.sun.star.reflection.XIdlReflection is an important entry point for the Uno Reflection API. The XIdlReflection interface has two methods that each return a com.sun.star.reflection.XIdlClass interface for a given name (method forName()) or any value (method getType()). The above IDL file shows us both methods :
// IDL module com { module sun { module star { module reflection { interface XIdlReflection: com::sun::star::uno::XInterface { com::sun::star::reflection::XIdlClass forName( [in] string aTypeName ); com::sun::star::reflection::XIdlClass getType( [in] any aObj ); }; }; }; }; };
Now we see we have to inquire about the XIDLClass interface. Here is the corresponding IDL file :
// IDL module com { module sun { module star { module reflection { interface XIdlField; interface XIdlMethod; interface XIdlArray; interface XIdlClass: com::sun::star::uno::XInterface { /** Deprecated. Do not call. */ sequence<XIdlClass> getClasses(); /** Deprecated. Do not call. */ XIdlClass getClass( [in] string aName ); boolean equals( [in] XIdlClass Type ); boolean isAssignableFrom( [in] XIdlClass xType ); com::sun::star::uno::TypeClass getTypeClass(); string getName(); /** Deprecated. Do not call. */ com::sun::star::uno::Uik getUik(); sequence<XIdlClass> getSuperclasses(); /** Deprecated. Do not call. */ sequence<XIdlClass> getInterfaces(); XIdlClass getComponentType(); XIdlField getField( [in] string aName ); sequence<XIdlField> getFields(); XIdlMethod getMethod( [in] string aName ); sequence<XIdlMethod> getMethods(); XIdlArray getArray(); void createObject( [out] any obj ); }; }; }; }; };
where we can see many deprecated methods.
An example showing the XIdlReflection interface in action could be :
[cpp]
// Listing 7 Using XIdlReflection interface
// C++
void LittleXRay(OUString OUStr,Reference< XMultiServiceFactory > rOServiceManager) {
// Don't forget to add : using namespace com::sun::star::reflection;
// Don't forget to add : #include <com/sun/star/reflection/XIdlReflection.hpp>
// Don't forget to add "com.sun.star.reflection.XIdlReflection \" in the makefile
Reference< XIdlReflection >rIDLReflection = Reference< XIdlReflection >
( rOServiceManager->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ))), UNO_QUERY );
if (! rIDLReflection.is()) { printf("Error XIDLRflection\n"); return;} Reference< XIdlClass > rIDLClass=rIDLReflection->forName(OUStr); // OUString::createFromAscii("com.sun.star.frame.XDesktop"));
Sequence< Reference< XIdlClass > > SeqIdlClass = rIDLClass->getSuperclasses();
printf("******** superClasses :(%d)\n",SeqIdlClass.getLength());
for (int i=0;i<SeqIdlClass.getLength();i++){
OString o = OUStringToOString( SeqIdlClass[i]->getName(),RTL_TEXTENCODING_ASCII_US );
printf("%s\n", o.pData->buffer );
} Sequence< Reference< XIdlMethod > > SeqIdlMethods = rIDLClass->getMethods(); printf("******** methods : (%d)\n",SeqIdlMethods.getLength()); for (int i=0;i<SeqIdlMethods.getLength();i++){ OString o = OUStringToOString( SeqIdlMethods[i]->getName(),RTL_TEXTENCODING_ASCII_US );
printf("%s\n", o.pData->buffer );
} // Don't forget to add : #include <com/sun/star/reflection/XIdlField2.hpp> // Don't forget to add : "com.sun.star.reflection.XIdlField2 \" in the Makefile Sequence< Reference< XIdlField > > SeqIdlFields = rIDLClass->getFields(); printf("******* Fields : (%d)\n",SeqIdlFields.getLength()); for (int i=0;i<SeqIdlFields.getLength();i++){
OString o = OUStringToOString( SeqIdlFields[i]->getName(),RTL_TEXTENCODING_ASCII_US );
printf("%s\n", o.pData->buffer );
}
}
which could be called with this code :
[cpp]
// Listing 8
// C++
LittleXRay(OUString::createFromAscii("com.sun.star.frame.XDesktop"),rOfficeServiceManager);
and which could give the listing above as a result :
******** superClasses :(1) com.sun.star.uno.XInterface ******** methods : (9) queryInterface acquire release terminate addTerminateListener removeTerminateListener getComponents getCurrentComponent getCurrentFrame ******* Fields : (0)
The previous C++ listing is a very simple example. The XIdlMethod interface can provide more information than presented. The corresponding IDL files shows these possibilities :
// IDL module com { module sun { module star { module reflection { interface XIdlClass; interface XIdlMethod: com::sun::star::reflection::XIdlMember { XIdlClass getReturnType(); sequence<XIdlClass> getParameterTypes(); sequence<ParamInfo> getParameterInfos(); sequence<com::sun::star::reflection::XIdlClass> getExceptionTypes(); com::sun::star::reflection::MethodMode getMode(); any invoke( [in] any obj, [inout] sequence<any> args ) raises( com::sun::star::lang::IllegalArgumentException, com::sun::star::reflection::InvocationTargetException ); }; }; }; }; };
If you want to show the returned type of a method, for instance, the getReturnType method is your friend. An example is presented now :
[cpp]
//Listing 9 Improve the returned information
// C++
Sequence< Reference< XIdlMethod > > SeqIdlMethods = rIDLClass->getMethods();
printf("******** methods : (%d)\n",SeqIdlMethods.getLength());
for (int i=0;i<SeqIdlMethods.getLength();i++){
OString o = "("
+ OUStringToOString( SeqIdlMethods[i]->getReturnType()->
getName(),RTL_TEXTENCODING_ASCII_US )
+ ") " + OUStringToOString( SeqIdlMethods[i]->getName(), RTL_TEXTENCODING_ASCII_US );
printf("%s\n", o.pData->buffer );
} When executing this code,
******** methods : (9) (any) queryInterface (void) acquire (void) release (boolean) terminate (void) addTerminateListener (void) removeTerminateListener (com.sun.star.container.XEnumerationAccess) getComponents (com.sun.star.lang.XComponent) getCurrentComponent (com.sun.star.frame.XFrame) getCurrentFrame
is now printed out. All the information on the parameters can be found with the same way but using getParamaterTypes() and getMode() methods.
The Figure below is a summary of the XIdlReflection interface programming. The corresponding code is given in Listing 10 instead of Listing 7 latter querying the XIdlReflection in one statement and former in two statements.
[cpp]
//Listing 10 Obtaining XIdlReflection with two statements
//C++
Reference< XInterface > xInterface = rOServiceManager->createInstance(
OUString::createFromAscii( "com.sun.star.reflection.CoreReflection" ));
Reference< XIdlReflection >rIDLReflection(xInterface,UNO_QUERY); if (! rIDLReflection.is()) printf("Error XIDLRflection\n");