FR/Documentation/Fichiers IDL et C++

From Apache OpenOffice Wiki
< FR‎ | Documentation
Revision as of 14:35, 9 July 2008 by SergeMoutou (Talk | contribs)

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

(Cette introduction est faite avec l'aide de :http://udk.openoffice.org/cpp/man/component_tutorial.html ) Vous devez commencer à être habitué si vous êtes parvenus jusqu'ici en lisant tous les chapitres précédents à la terminologie service/interface qui prévaut pour la programmation UNO. Cette terminologie n'étant pas universelle, je me permet d'en rappeler quelques éléments.


Services et Interfaces

Introduction

Voir http://api.openoffice.org/basic/man/tutorial/tutorial.pdf (chapitre 2) Dans API OpenOffice, un "service" est un concept abstrait qui fournit certaines interfaces et propriétés/attributs. Comme le souligne le Guide du développeur : “les propriétés sont des données dans un objet qui sont triées par nom sur une interface générique pour un accès de la propriété”. Il serait mieux de distinguer attribut et propriété. Mais nous ne le faisons pas pour le moment.

Comme on peut le voir en Figure 8, un service possède plusieurs propriétés et une interface correspond à plusieurs méthodes qui trouvent un moyen de changer les propriétés. Prenons une voiture pour illustrer ces concepts. La voiture fournit deux interfaces concrètes : XAccelerationControl et XDrivingDirection. Deux méthodes d'exportation d'interface, la première pour accélérer et ralentir, la seconde pour faire tourner la voiture à droite ou à gauche (voir Figure 9). Pourquoi deux (ou plusieurs) interfaces ? C'est seulement pour réunir des fonctionnalités caractéristiques. Pensez à une vraie voiture où ces interfaces sont séparées (le volant d'un côté et les pédales de l'autre) et ce qui se passerait si seulement les pieds dirigeaient ces deux interfaces ?

Dans API OpenOffice, les modules groupent des services, des interfaces, des types, des énumérations et autres structures données (voir Figure 10). C'est impossible de comprendre un tel dessin sans se poser un certain nombre de questions et, en particulier, comment est-ce que nous voyons ce module quand il est utilisé dans un programme ?


Pour répondre à cette question, nous choisissons OOoBasic :

'Listing 1
REM  *****  BASIC  *****
'en premier, créez le service
oSimpleComponent = CreateUnoService( "my_module.MyService1" )
'call the unique method
oSimpleComponent.methodOne()
....
'first create the service
oSimpleComponent2 = CreateUnoService( "my_module.MyService2" )
'call one of both method
oSimpleComponent.methodTwo()
...

Les règles de Danny Brewer Les services sont similaires aux objets en java.

  1. Un service peut hériter de rien ou d'un autre service. (auquel on peut appliquer récursivement cette règle)
  2. Un service peut inclure zéro ou plusieurs services. (auxquels on peut appliquer récursivement ces règles)
  3. Un service peut exporter des interfaces.
  4. Un service peut avoir des propriétés.
  5. Une interface peut hériter d'aucune ou d'une autre interface (à laquelle on peut appliquer récursivement cette règle).
  6. Une interface peut inclure zéro ou plusieurs interfaces (auxquelles on peut appliquer récursivement ces règles).
  7. Une interface peut exécuter des méthodes.
  8. Une interface est toujours nommées par un nom commençant par un X.

De ces règles vous pouvez déduire que les méthodes sont TOUJOURS trouvées dans des interfaces, et les propriétés sont TOUJOURS trouvées dans des services.

Specification IDL

Les interfaces utilisent un spécial langage de définition de l'Interface (IDL). UNO utilise UNO-IDL comme le langage de définition de l'interface. Le Langage de définition de l'Interface (IDL) est un langage descriptif (et non un langage de programmation) décrivant l'existence des interfaces qui seront rendues effectives par les objets. Avec IDL, vous définissez le nom de l'interface, les noms de chacun des attributs et méthodes. Une fois que vous avez créé les fichiers IDL, vous pouvez utiliser un compilateur IDL pour générer les fichiers d'en-tête dans le langage de programmation C++. La façon de spécifier des modules simples avec IDL est si claire que nous choisissons de commencer en premier seulement des exemples.

Specifier une interface

Nous prenons comme exemple, l'interface XdrivingDirection de la Figure 9.

//Listing 143 Interface imaginaire XDrivingDirection
// IDL
interface XDrivingDirection
	{
		void turnLeft();
		void turnRight();
	};

Spécifier un service

L'exemple de la Figure 9 est toujours utilisé, voici la spécification IDL correspondante :

//Listing 144 Spécification d'un service « car »
// 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;
	};

Nous voyons apparaître un type float et nous donnons d'autres types IDL plus loin.

Spécifier un module

Les modules sont un moyen de regrouper des services. Cette notion correspond plutôt à une bibliothèque et n'a que peu d'importance pour le programmeur C++ (sauf s'il désire réaliser des extensions composants ou addin par exemple). Nous donnons quand même ici la spécification IDL correspondant à un module :

//Listing 145 Spécification IDL du module my_module
// 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;
		};
};

Plus loin avec IDL

Les types IDL sont décrits dans le tableau ci-dessous : char 16-bit unicode character type boolean boolean type; vrai ou faux 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

Les méthodes peuvent avoir des arguments. Chaque argument dans la liste des arguments doit commencer avec un des drapeaux de direction [in], [out] ou [inout] avant qu'un type connu et identificateur pour l'argument soit donné. Nous donnons un exemple que nous rencontrerons souvent dans ce document , un compteur :

//Listing 146 Module IDL décrivant un compteur
// IDL
module my_module
{
  interface XSomething 
  {
	long getCount();
	void setCount( [in] long nCount );
	long increment();
	long decrement();
  };
  service MyService
  {
    interface XSomething;
  };
};

Une interface peut être dérivée à partir d'une interface de base. Une interface dérivée peut déclarer ses propres attributs et ses méthodes. Les attributs et méthodes hérités ne peuvent pas être redéfinies dans l'interface dérivée. Un exemple d'héritage de l'interface :

//Listing 147 Héritage dog de annimal
//IDL
interface animal {
	attribute long age;
};
interface dog : animal {
	attribute short leg;
}

L'héritage multiple est aussi possible

interface dog : animal, friend {

L'héritage dans le service est présenté dans le prochain chapitre. Dans la terminologie objet OOo, il y a une différence entre attribut et propriété, différence qui se manifeste par leurs façons respectives d'y accéder. On accède aux propriétés avec setPropertyValue(PropertyName,Any) alors qu'on accède aux attributs avec la méthode set/get(AttributeName). Nous avons déjà rencontré la manipulation des propriétés lors de l'examen des formes.

Collecter de l'information UNO avec les fichiers IDL

Il y a plusieurs possibilités pour trouver de l'information sur UNO. La première est d'utiliser OOoBasic et l'outil XRay de Bernard Marcelly (disponible ici http://www.ooomacros.org/dev.php#101416). Point négatif : OOoBasic ne montre pas les propriétés et les méthodes exactes, quelques unes sont rajoutées parce qu'elles sont disponibles en OooBasic. L'autre possibilité est d'aller à l'adresse internet suivante : http://api.openoffice.org/docs/common/ref/index-files/index-1.html qui fournit la même information mais probablement de manière plus lisible. Nous avons fourni des exemples dans les chapitres antérieurs (en particulier chapitre 8...) et normalement le lecteur a des compétences sur le sujet. Le point de vue de Danny Brewer Néanmoins, il est important de comprendre le concept d'un "service" dans les documents sur l'API. Un service est juste une façon de grouper...

  1. d'autres services encore
  2. des interfaces

La partie (1) “d'autres services encore”, signifie bien sûr, qu'il y a même plus d'interfaces disponibles au service original. Laissez moi vous montrer différents exemples.

SpreadsheetDocument est un service. SpreadsheetDocument hérite du service OfficeDocument.

Par conséquent, l'ensemble combiné d'interfaces de SpreadsheetDocument et OfficeDocument est accessible à un document de la Feuille de calcul (qui est bien sûr un SpreadsheetDocument).

Donc, bien que le composant chargé depuis l'URL retourne une interface, cette interface représente un service sous-jacent qui est un SpreadsheetDocument. En regardant les documents de l'API, vous pouvez dire quelles interfaces valides vous pouvez mettre en oeuvre. SpreadsheetDocument possède un service XSpreadsheetDocument. OfficeDocument possède un service XPrintable et XStorable. Comme SpreadsheetDocument est hérité de OfficeDocument, il est aussi valide de demander soit l'interface XPrintable soit l'interface XStorable à partir de ce service SpreadsheetDocument.

Maintenant, remplaçons dans le paragraphe précédent, les documents tableurs par les documents textes et tout le discours précédent est encore valide. Comment expliquer ce qu'est un service sous-jacent ?

Il n'y a pas de formules magique pour cela. En principe, c'est évident. Si vous démarrez un tableur, par exemple, alors vous avez le service SpreadsheetDocument.

De la même façon, si je crée un objet par son nom de service.....

' obtention d'un service en OOoBasic
oShape = oDoc.createUnoService( "com.sun.star.drawing.EllipseShape" )

alors je sais quel service c'est, parce que j'ai donné le nom du service dans l'instruction.

Oui, vous pouvez toujours dire quelles interfaces sont disponibles si vous savez le nom du service, et ce, seulement en regardant la documentation de l'API. Aucune hypothèse. Aucun besoin der XRay. C'est une science absolue. Les multiples interfaces valides sont les interfaces du service lui-même, et de tous les services qui seront hérités de ce service.

Dans certains cas, il est évident de savoir quels services vous avez.

Si vous appelez getCellRangeByName(), alors vous obtenez un service SheetCellRange. Si vous appelez getCellByPosition(), alors vous avez un service SheetCell. Beaucoup de choses identiques sont disponibles dans ces deux services SheetCell et SheetCellRange, mais ils sont de nature différents. Le service SheetCellRange représente un groupe rectangulaire de cellules tandis que le service SheetCell concerne une cellule unique. Il y a évidemment des choses que l'on peut faire avec une cellule unique mais pas avec un groupe de cellule.

Il y a aussi d'autres possibilités. Si vous obtenez un service com.sun.star.table.CellRange à partir d'une table sous OOoWriter ce sera différent que si vous l'obtenez depuis une feuille de calcul, puisque ce sera un com.sun.star.sheet.SheetCellRange. Le service SheetCellRange est une version étendue du service CellRange. Lequel des deux services est obtenu dépend donc si votre demande getCellRangeByName() est réalisée à partir d'une table ou à partir d'une feuille de calcul.

Parfois, spécialement pour l'application OooWriter, seul le guide du développeur est une aide précieuse, donnant des informations sur les services obtenus à partir d'autres services et des appels API. Mais il est toujours vrai que lorsque l'on connaît le service que l'on a, on peut en déduire directement, seulement à partir de la documentation de l'API toutes les interfaces qu'il est possible de demander. Pas d'essais inutiles, c'est une science exacte.

Un exemple concret

Les fichiers IDL sont disponibles avec dans le dossier <OpenOffice.org1.1_SDK>/idl/. Évidemment, le problème avec cette solution est que nous voyons uniquement l'API UNO du SDK installé, lequel peut être légèrement différent de notre Openoffice.org. Cependant, nous expliquerons cette possibilité après avoir mentionné juste une autre solution : l'exploration de la base de registres (voir chapitre 10) On veut maintenant montrer un exemple. On commence à partir d'un

com::sun::star::document::OfficeDocument et du nom du service, on en déduit sa position dans l'arborescence <OpenOffice.org1.1_SDK>/idl/com/sun/star/document/OfficeDocument.idl

Ce fichier est présenté ci-dessous, (sans les commentaires) :

//Listing 148
//IDL
service OfficeDocument
{
	interface com::sun::star::frame::XModel;
    interface com::sun::star::util::XModifiable;
	interface com::sun::star::frame::XStorable;
	interface com::sun::star::view::XPrintable;
    [optional] interface XEventBroadcaster;
	[optional] interface XEventsSupplier;
    [optional] interface XDocumentInfoSupplier;
    [optional] interface XViewDataSupplier;
    [optional] interface com::sun::star::view::XPrintJobBroadcaster;
	[property, optional] boolean AutomaticControlFocus;
	[property, optional] boolean ApplyFormDesignMode;
};

Cela nous conduit à la Figure 11. Si on examine maintenant le ::com::sun::star::text::TextDocument on trouve dans <OpenOffice.org1.1_SDK>/idl/com/sun/star/text/TextDocument.idl

//Listing 149
service TextDocument
{
	service com::sun::star::document::OfficeDocument;
	interface com::sun::star::text::XTextDocument;
	interface com::sun::star::util::XSearchable;
	interface com::sun::star::util::XRefreshable;
	....
};

Comme on peut voir, ce service est dépendant du premier présenté à la Figure 11.


Cette dépendance est en fait un héritage et est représentée à la Figure 12 (avec sa représentation standard par une flèche). La représentation complète UML de cet exemple peut être trouvée dans le guide de développeur : http://api.openoffice.org/docs/DevelopersGuide/FirstSteps/FirstSteps.htm

IDL et C++

Ce problème est développé dans le guide du développeur : voir http://api.openoffice.org/docs/DevelopersGuide/ProfUNO/ProfUNO.htm#1+4+2+UNO+C%2B%2B+Binding Obtention d'une interface en C++ En C++, vous avez seulement des variables de type interface. Un des problèmes les plus souvent rencontrés met en oeuvre une interface. Ce problème se produit très rarement dans OooBasic mais très souvent dans C++/Java. On peut trouver un exemple dans le chapitre 2 et beaucoup d'autres dans le 3. Comme exemple, on suppose qu'on a obtenu un com::sun::star::document::officeDocument service. En général, c'est fait par quelque chose comme :

//Listing 150
//C++
Reference<com::sun::star::document::officeDocument> OfDoc = something_to_get_this_service();

ou

//Listing 151
//C++
using namespace com::sun::star::document;
....
Reference<officeDocument> OfDoc = something_to_get_this_service();

et nous voulons mettre en oeuvre l'interface XStorable pour sauver notre document. Trois étapes sont impliquées dans cette action : 1) Ajoutez la ligne de votre code comme la question d'UNO

// C++
// query from com::sun::star::frame::XStorable interface
	Reference< XStorable > oToStore (OfDoc, UNO_QUERY);

2) Ajouter à l'aide d'une directive d'inclusion les fichiers hpp correspondants. Il faut ajouter aussi les espaces de nommage correspondants. L'inclusion est faite par :

//C++
	#include <com/sun/star/frame/XStorable.hpp>

et la gestion des espaces de nommage par :

//C++
	using namespace com::sun::star::frame;

3) Ajouter les types correspondants dans le makefile comme montré ci-dessous dans la ligne com.sun.star.frame.XStorable \ qui est ajoutée

# Listing 152 Makefile 
# 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

Apprendre à réaliser ces trois étapes est essentiel pour une programmation en C++ : il vous sera impossible de réaliser un programme sans demander à un moment donné une interface ou un service. Ce problème de demande d'interface a déjà été abordé aux chapitres 3 et 4. Un autre problème technique est la correspondance des types : vous avez un fichier IDL, comment sont compilés les types ? La prochaine section aborde le sujet et peut être évitée pour une première lecture : allez donc alors au chapitre 6.

Correspondances pour les modules et interfaces

Par exemple :

//Listing 153
// IDL 
module M 
{ struct E { long L; 
  }; 
};

est compilé en C++ comme

 
//Listing 154
// C++ 
namespace M 
{ struct E 
  { Long L; }; 
}

et on peut faire référence à E en dehors de M par M::E. D'autre part une instruction de nommage peut être utilisée pour référer cette structure simplement comme E :

//Listing 155
// C++ 
using namespace M; 
E e;
  e.L = 3;

Une autre alternative est d'employer la directive de nommage seulement pour M::E :

//Listing 156
// C++ 
using M::E;
  E e;
  e.L = 3;

Une interface est réalisée à l'aide d'une classe C++ qui contient les définitions des types, constantes et exceptions définies dans l'interface. L'exemple ci-dessous montre le comportement de cette correspondance pour une interface : Listing 157 // IDL interface A{

 struct S {
   short field;
  };
};

est compilée en : Listing 158 // C++ class SAL_NO_VTABLE A {

 struct S {
   short fiel;
 };

}; //A

On peut utiliser aussi : Listing 159 // Conformant uses

A::S s; // declare a struct variable 

s.field = 3; // field access // Non-conformant uses: // one cannot declare an instance of an interface class... A a; // ...nor declare a pointer to an interface class... A *p; // ...nor declare a reference to an interface class. void f(A &r); Le service de Core reflection et son interface XIdlReflection

To do Traduire des programmes OooBasic en C++

La traduction des programmes OooBasic en C++ n'est pas si immédiate que cela. Les interfaces et attributs vus par les programmes OooBasic sont construite à travers un pont pour des questions de facilité. Alors ce qui est vu en OooBasic ne sera pas forcément vu en C++. Une des conséquences de tout cela est qu'il est impossible de réaliser cette traduction sans passer un peu de temps avec les fichiers IDL. To do

Personal tools