Un aperçu de XPCOM

Cet article nécessite une relecture rédactionnelle. Voici comment vous pouvez aider.

Cette section est présentée comme un tutoriel sur la création de composants XPCOM, mais elle couvre tous les principaux aspects, les concepts et la terminologie du modèle de composant XPCOM tout au long de sa conception.

Ce chapitre fournit un rapide tour d'horizons sur XPCOM - une introduction aux concepts de base, des technologies XPCOM et du développement de composants. Les paragraphes de ce chapitre présentent des concepts de haut niveaux, de sorte que nous puissions les approfondir et de les utiliser avec plus de familiarité dans le tutoriel lui-même, qui décrit la création d'un composant Mozilla appelé WebLock .

La solution XPCOM

Le Cross Platform Component Object Module (XPCOM) est un cadre qui permet aux développeurs de fractionner un projets monolithiques en morceaux modulaires. Ces morceaux, appelés composants , sont ensuite assemblés de nouveau ensemble à l'exécution.

Le but de XPCOM est de mettre au point les différentes parties de logiciel en les construisant indépendamment les uns des autres. Afin de permettre l'interopérabilité entre les composants d'une application, XPCOM sépare la mise en œuvre d'un composant de l'Interface . Mais XPCOM fournit également plusieurs outils et bibliothèques qui permettent le chargement et la manipulation de ces composants, des services qui aident le développeur à écrire du code modulaire multi-plateforme, et le soutien des versions, de sorte que les composants peuvent être remplacés ou mis à niveau sans casser ou avoir à recréer l'application . En utilisant XPCOM, les développeurs créent des composants qui peuvent être réutilisés dans différentes applications ou qui peut être remplacé pour changer la fonctionnalité des applications existantes.

XPCOM soutient non seulement le développement de composant logiciels, il fournit également une grande partie des fonctionnalité de la plate-forme de développement fournit, tels que:

  • la gestion de composant
  • le fichier abstrait
  • l'objet message
  • la gestion de la mémoire

Nous allons décrire les éléments ci-dessus en détail dans les chapitres à venir, mais pour l'instant, il peut être utile de penser à XPCOM en tant que plate-forme pour le développement de composants , dans lequel des caractéristiques telles que celles énumérées ci-dessus sont fournis.

Gecko

Bien qu'il soit à certains égards structurellement similaires à Microsoft COM, XPCOM est conçu pour être utilisé principalement au niveau de l'application. L'utilisation la plus importante de XPCOM est dans Gecko , open source, conforme aux standards, navigateur Web intégrable et boîte à outils pour la création de navigateurs Web et autres applications.

XPCOM est le moyen d'accéder aux fonctionnalités de la bibliothèque Gecko pour l'utilisation ou l'extension de Gecko. Ce livre met l'accent sur l'extension mais les explications de ce livre seront important pour le développeurs d'application Gecko embarquées.

Gecko est utilisé dans de nombreuses applications internet, la plupart des navigateurs et notamment Mozilla Firefox.

Composants

XPCOM vous permet de briser les gros projets logiciels en petits morceaux connus en tant que composants. Ils sont généralement contenus dans des bibliothèques binaires réutilisables (DLL sur Windows, DSO sur Unix), qui peuvent comprendre un ou plusieurs composants. Lorsque deux ou plusieurs composants connexes sont regroupées dans une bibliothèque binaire, la bibliothèque est appelée module.

Modulaire, la programmation à base de composants logiciels rend plus facile le développement et la maintenance:

Avantage Description
Réutilisation Code modulaire peut être réutilisé dans d'autres applications et d'autres contextes.
Mises à jour Vous pouvez mettre à jour les composants sans avoir à recompiler l'application entière.
Performance Lorsque le code est modulaire, les modules qui ne sont pas nécessaires immédiatement peuvent être chargées partiellement, ou pas chargés du tout, ce qui peut améliorer les performances de votre application.
Maintenance Même lorsque un composant est obsolète, la conception de votre application modulaire vous permet  plus facilement de maintenir les parties de l'application que vous intéressent.

Mozilla a plus de quatre millions de lignes de code, et pas une seule personne ne comprend l'ensemble du code source. La meilleure façon d'aborder un projet de cette taille est de le diviser en modules. La bibliothèque de réseau, par exemple, est constitué de composants pour chacun des protocoles, HTTP, FTP, et d'autres, qui sont groupés et liés dans une seule bibliothèque. Cette bibliothèque est le module de gestion de réseau, également appelé "necko."

Mais il n'est pas toujours souhaitable de diviser les choses. Le composant HTTP de Gecko n'expose pas les classes privés qu'elle utilise comme des composants séparés. Les objets interne au composante reste interne, et ne soit pas manipulables par XPCOM.

Interfaces

Comment segmenter du code? L'idée de base est d'identifier les segments fonctionnellement liés et comprendre comment ils communiquent entre eux. Les canaux de communication entre les différentes composants forment ces limites, et lorsque ces limites sont formalisées on parle d'interfaces .

Les interfaces ne sont pas une idée nouvelle en programmation. Nous avons tous l'habitude interfacer depuis notre premier programme "HelloWorld", où est l'interface entre le code que nous avons écrit - le code d'application - et le code d'impression. Le code d'application utilisé une interface à partir d'une bibliothèque, stdio , et imprime la texte "hello world" sur l'écran. La différence ici est que l'application "HelloWorld" dans XPCOM trouve cette fonctionnalité d'affichage à l'exécution et n'a pas à connaître stdio quand il est compilé.

Interfaces permettent aux développeurs d' encapsuler la mise en œuvre et de fonctionnement interne de leur logiciel, et permettent aux clients d'ignorer la façon dont les choses sont faites, il suffit d'utiliser ce logiciel.

Interfaces et programmation par contrat

Une interface forme un accord contractuel entre les composants et les clients. Il n'y a pas de code qui oblige ces accords, mais les ignorer peut être fatal. Dans la programmation à base de composants, un composant garantit que les interfaces qu'il fournit seront immuable - qu'ils vont offrir le même accès aux mêmes méthodes à travers différentes versions du composante - l'établissement d'un contrat avec les logiciels clients qui l'utilisent. À cet égard, la programmation basé sur l'interface est souvent désigné comme la programmation par contrat .

Interfaces et Encapsulation

Aux limites des composants, l'abstraction est crucial pour la maintenabilité du logiciel et la réutilisabilité. Considérons, par exemple, une classe mal encapsulé. L'utilisation d'une méthode d'initialisation publique librement disponibles, comme l'exemple ci-dessous, peut causer des problèmes.

SomeClass Class Initialization

class SomeClass{
  public:
    // Constructeur
    SomeClass();
    // Destructeur virtuel
    virtual ~SomeClass();
    // method init
    void Init();
    void DoSomethingUseful();
};

Pour que ce système fonctionne correctement, l'utilisateur de cette classe doit porter une attention particulière à tout ce que le créateur de cette classe a établi. C'est l'accord contractuel avec cette classe non encapsulé: un ensemble de règles qui définissent quand chaque méthode peut être appelée et ce qu'elle est censé faire. Une règle peut spécifier que DoSomethingUseful ne peut être appelé après un appel à init () . La méthode DoSomethingUseful peut veiller à ce que la condition soit satisfaite.

En plus du code correctement commenté pour les règles d'utilisation de Init() , le développeur peut prendre quelques mesures pour que ce contrat soit plus clair. Tout d'abord, le constructeur d'un objet peut être encapsulé, et une classe virtuelle DoSomethingUseful peut être mis à disposition. De cette façon, le constructeur et l'initialisation peuvent être complètement cachés des utilisateurs de la classe. Dans cette situation, "semi-encapsulé", la seule partie de la classe qui est exposé est une liste bien définie des méthodes appelables (i.e, l'interface). Une fois que la classe est encapsulé, la seule interface que le client verra est la suivante:

Encapsulation de SomeInterface

class SomeInterface{
  public:
    virtual void DoSomethingUseful() = 0;
};

La mise en œuvre peut alors dériver de cette classe par l'utilisation de la méthode virtuelle. Les utilisateurs de ce code peuvent ensuite créer l'objet (voir utilisation ) et encapsuler aussi la mise en œuvre. Avec XPCOM, les usagers sont ignorant du fonctionnement du composants et comptent sur ​​l'interface pour donner accès aux fonctionnalités nécessaires.

L'interface de base nsISupports

Les deux fondamentaux de la programmation composant sont basé sur component lifetime(durée de vie), appelé aussi object ownership, et interface querying, sois l'identification des interfaces d'un composant prises en charge lors de l'exécution. Ce chapitre présente la mère de toutes les interfaces XPCOM - nsISupports , qui fournit les solutions à ces deux problèmes pour les développeurs XPCOM.

Object Ownership

Avec XPCOM, parce que les composants peuvent mettre en œuvre un certain nombre d'interfaces, ils doivent être référencés . Quand un composant est créé, un entier interne au composant est incrémenté - connu comme compteur de référence. Au cours de la vie du composant, le compteur de référence augmente et diminue. Lorsque le composant n'a plus d'utilité, le compteur de références atteint zéro, et le composant est détruit.

Lorsque les clients utilisent des interfaces de façon responsable, cela peut être un processus très simple. XPCOM dispose d'outils pour rendre encore cela plus facile. Il peut soulever des problèmes réels de maintenance lorsque, par exemple, un client utilise une interface et oublie de decrémenter le nombre de références. Lorsque cela se produit, les interfaces ne peuvent jamais être libérés et provoqueront des fuites de mémoire. Le système de comptage de référence est, comme beaucoup de choses dans XPCOM, un contrat entre les clients et les implémentations. Il fonctionne quand les utilisateur le respecte, mais quand ils ne le font pas, les choses peuvent aller mal. C'est le rôle de la fonction qui crée le pointeur d'interface pour ajouter la référence initiale, ou owning reference, d'éviter ces problemes.

Pointeurs avec XPCOM

Dans XPCOM, les pointeurs se réfèrent à l'interface pointeurs. La différence est subtile, puisque les pointeurs d'interface et les pointeurs réguliers sont tout simplement deux adresses dans la mémoire. Mais un pointeur d'interface est connu pour mettre en œuvre l'interface de base nsISupports, et peut donc être utilisé pour appeler des méthodes telles que AddRef, Release, ou QueryInterface.

nsISupports, illustré ci-dessous, fournit les fonctionnalités de base pour faire face à la création d'interface et de comptage de référence. Les membres de cette interface, QueryInterface, AddRef et Release , fournissent les moyens de base pour obtenir la bonne interface d'un objet, incrémenter le compteur de référence, et de libérer les objets une fois qu'ils ne sont plus utilisés.

L'interface nsISupports

class Sample: public nsISupports{
  private:
    nsrefcnt mRefCnt;
  public:
    Sample();
    virtual ~Sample();
    NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
    NS_IMETHOD_(nsrefcnt) AddRef(void);
    NS_IMETHOD_(nsrefcnt) Release(void);
};

Les différents types utilisés de l'l'interface sont décrites dans la section Types XPCOM. La mise en œuvre complète de nsISupports est indiquée ci-dessous. Voir Une implémentation de référence de QueryInterface pour des informations détaillées.

Mise en œuvre de l'interface nsISupports

// Initialiser le compteur de référence à 0
Sample::Sample() : mRefCnt(0){ 
}
Sample::~Sample(){
}
// la mise en œuvre générique de QI
NS_IMETHODIMP Sample::QueryInterface(const nsIID &aIID,
                                  void **aResult){
  if (!aResult) {
    return NS_ERROR_NULL_POINTER;
  }
  *aResult = NULL;
  if (aIID.Equals(kISupportsIID)) {
    *aResult = (void *) this;
  }
  if (!*aResult) {
    return NS_ERROR_NO_INTERFACE;
  }
  // ajoute une reference
  AddRef();
  return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt) Sample::AddRef(){
  return ++mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) Sample::Release(){
  if (--mRefCnt == 0) {
    delete this;
    return 0;
  }
  // optional: retourn le nombre de reference
  return mRefCnt;
}

Object Interface Discovery

Héritage est un autre sujet très important dans la programmation orientée objet. L'héritage est le moyen par lequel une classe est dérivée d'une autre. Quand une classe hérite d'une autre classe, la classe hérite peut remplacer les comportements par défaut de la classe de base sans avoir à copier tout le code de cette classe et créer ainsi une classe plus spécifique, comme dans l'exemple suivant:

Héritage de classe simple

class Shape{
  private:
    int m_x;
    int m_y;
  public:
    virtual void Draw() = 0;
    Shape();
    virtual ~Shape();
}; 
class Circle : public Shape{
  private:
    int m_radius;
  public:
    virtual Draw();
    Circle(int x, int y, int radius);
    virtual ~Circle();
};

Circle(cercle) est une classe dérivée de Shape(forme) . Un cercle est une forme , en d'autres termes, mais une forme n'est pas nécessairement un cercle . Dans ce cas, forme est la classe de base et cercle est une sous-classe de forme .

Avec XPCOM, toutes les classes dérivent de l'interface nsISupports, de sorte que tous les objets héritent de nsISupports. Avec Héritage Class simple , par exemple, vous êtes en mesure de savoir si la forme est un cercle et dans ce cas de l'utiliser comme un cercle. Ces à quoi la caractéristique QueryInterface de nsISupports est destinée: elle permet aux utilisateurs de trouver et d'accéder aux différentes interfaces en fonction de leurs besoins.

En C++, vous pouvez utiliser une fonctionnalité assez avancé connu sous le nom de dynamic_cast<> , qui lève une exception si l'objet forme n'est un cercle . Mais les exceptions levants RTTI(Run-time type information) ne sont pas une option en raison de la lourdeur et de la compatibilité sur de nombreuses plates-formes, XPCOM fait les choses différemment.

Exceptions avec XPCOM

Les exceptions C++ ne sont pas pris en charge directement par XPCOM. Les exceptions doivent être manipulés dans le composant XPCOM, avant de franchir les frontières de l'interface. Toutes les méthodes de l'interface doivent retourner une valeur d'erreur nsresult (voir référence de l'API XPCOM pour une liste de ces codes d'erreur). Ces résultats de code d'erreur deviennent les «exceptions» que gère XPCOM.

Au lieu de tirer parti de RTTI du C++, XPCOM utilise la méthode QueryInterface qui passe l'objet à la bonne interface, si cette interface est pris en charge.

Chaque interface est pourvu d'un identifiant qui est généré à partir d'un outil nommée "uuidgen". Cet identifiant universel unique (UUID) est un numéro unique de 128 bits appelé IID. Ce n'est pas la même chose que l'ID d'un composant.

Quand un client veut découvrir si un objet prend en charge une interface donnée, le client passe l'IID assignée à cette interface dans la méthode QueryInterface de cet objet. Si l'objet prend en charge l'interface demandée, il ajoute une référence à lui-même et repasse un pointeur sur cette interface. Si l'objet ne prend pas en charge l'interface une erreur est renvoyée.

class nsISupports { 
  public:
    long QueryInterface(const nsIID & uuid,
                        void **result) = 0;
    long AddRef(void) = 0;
    long Release(void) = 0;
};

Le premier paramètre de QueryInterface est une référence à une classe nommée nsIID , qui est une encapsulation de base de l'IID. Parmi les trois méthodes sur de la classe nsIID, Equals ,Parse et ToString , Equal est de loin le plus important, car elle est utilisé pour comparer deux nsIID dans le processus d'interrogation d'interface.

Lorsque vous implémentez la classe nsISupports (et vous le verrez dans le chapitre Utilitaires XPCOM pour faciliter les choses comment les macros peuvent rendre ce processus beaucoup plus facile), vous devez vous assurer que les méthodes de la classe renvoient un résultat valable lorsque le client appelle QueryInterface avec le nsISupports IID. QueryInterface devrait soutenir toutes les interfaces que le composant soutient.

Dans les implémentations de QueryInterface, l'argument IID est comparer à la classe nsIID. Si il y a une corespondence, l'objet this pointeur est converti en void, le compteur de référence est incrémenté, et l'interface renvoyée à l'appelant. Si il n'y a pas de correspondance, la classe retourne une erreur et la valeur de sortie est null .

Dans l'exemple ci-dessus, il est assez facile d'utiliser un C-style cast. Mais le casting peut devenir plus compliqué et vous devez d'abord passer void avec le type demandé, parce que vous devez retourner le pointeur d'interface dans la table virtuelle(vtable) correspondant à l'interface demandée. Castings peut devenir un problème quand il y a une hiérarchie d'héritage ambigu.

Identifiants XPCOM

En plus de l'identifiant d'interface IID discuté dans la section précédente, XPCOM utilise deux autres identificateurs très important pour distinguer les classes et les composants.

Classes XPCOM Identifier

La classe nsIID est en fait un typedef de la classe nsID. Les autres typedefs de nsID , CID et IID, se réfèrent respectivement à des implémentations spécifiques d'une classe concrète et d'une interface spécifique.

La classe nsID fournit des méthodes comme Equals pour comparer les identificateurs dans le code. Voir identificateurs XPCOM pour plus d'information sur nsID.

CID

Un CID est un nombre de 128 bits qui identifie de manière unique une classe ou un composant de la même manière qu'un IID identifie de manière unique une interface. Le CID pour nsISupports ressemble à ceci:

00000000-0000-0000-C000-000000000046

La longueur d'un CID  peut être lourd à traiter dans le code, de sorte que très souvent, vous verrez #defines pour les CID et les autres identifiants utilisés, comme dans cet exemple:

#define SAMPLE_CID \ 
{ 0x777f7150, 0x4a2b, 0x4301, \ 
{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}} 

Vous verrez utilisé aussi NS_DEFINE_CID. Cette macro déclare une constante avec la valeur du CID:

static NS_DEFINE_CID(kWebShellCID, NS_WEB_SHELL_CID);

Un CID est parfois aussi désigné comme un identificateur de classe . Si la classe à laquelle un CID se réfère a plus d'une interface, il garanties que la classe implémente cette ensemble d'interfaces quand elle est publiée ou fixée.

Contrat ID

Un contract ID est une chaîne lisible utilisé pour accéder à un composant. Un CID ou un contract ID peuvent être utilisés pour accéder à un composant dans gestionnaire de composant. Le contract ID est utilisé pour le composant LDAP Opération :

"@mozilla.org/network/ldap-operation;1"

Le format du contract ID est formé du domaine, du module, du nom du composant séparés par des barres obliques et du numéro de version.

Comme un CID, un contract ID se réfère à une mise en œuvre plutôt qu'à une interface à l'instar IID. Mais un contract ID n'est pas liée à une mise en œuvre spécifique, contrairement au CID, il est donc plus général. Au lieu de cela, un contract ID spécifie seulement un ensemble donné d'interfaces qu'il met en œuvre, et un certain nombre de CID diffèrent peuvent intervenir en complément. Cette différence entre un contract ID et un CID est ce qui rend possible de remplacer des composants.

Utilisation

Une fois que le code est divisé en composants, le code client utilise habituellement l'opérateur new pour instancier des objets:

SomeClass* component = new SomeClass();

Ce modèle exige que le client connaisse le composant. Le factory design pattern peut être utilisé pour encapsuler la construction de l'objet. L'objectif du procédé est de créer un objet sans exposer les clients à la mise en œuvre et l'initialisation de cet objet. Dans l'exemple SomeClass, la construction et l'initialisation de SomeClass , qui implémente la classe abstraite SomeInterface, est contenu par la fonction New_SomeInterface:

Encapsuler le constructeur

int New_SomeInterface(SomeInterface** ret){
  // Créer l'objet
  SomeClass* out = new SomeClass();
  if (!out) return -1;
  // Initialisation de l'objet
  if (out->Init() == FALSE){
    delete out;
    return -1;
  }
  // conversion de types de l'interface
  *ret = static_cast<SomeInterface*>(out);
  return 0; 
} 

Factory est la classe qui gère effectivement la création des instances distinctes d'un composant. Dans XPCOM, les factories sont mises en œuvre par l'interface nsIFactory. Le modèle de conception utilise l'abstraction et encapsulalion de la construction et de l'initialisation de l'objet.

L'exemple de l'encapsulation du constructeur est une version simple et sans état ​​de factories, mais la programmation réel est généralement plus compliquée, ou les factories ont besoin de stocker l'état. Au minimum, la factory a besoin de préserver l'information des objets qu'elle a créée. Quand une factory gère les instances d'une classe construite dans une bibliothèque dynamique partagée, par exemple, elle doit savoir quand elle peut décharger la bibliothèque. Quand la factory conserve l'état, vous pouvez demander si il y a des références et savoir si la factory a créé des objets.

Un autre état ​​utile est de savoir si oui ou non un objet est un singleton . Par exemple, si la factory crée un objet qui est censé être un singleton, les appels suivants doivent retourner le même objet. Bien qu'il existe des outils et de meilleures façons de gérer les singletons (dont nous parlerons lorsque nous parlons de l'nsIServiceManager), un développeur peut vouloir utiliser cette information pour s'assurer que seul un objet singleton peut exister quelque soit l'usage.

Les exigences d'une classe factory peuvent être traitées de manière strictement fonctionnel, l'état étant détenu par des variables globales, mais il y a des avantages à utiliser des classes pour les factory. Lorsque vous utilisez une classe pour implémenter la fonctionnalité d'une factory, par exemple, vous utilisez nsISupports, qui vous permet de gérer la durée de vie de l'objets lui-mêmes. Ceci est important quand vous voulez regrouper des ensembles de factories et déterminer si elles peuvent être déchargées. Un autre avantage de l'utilisation de nsISupports est que vous pouvez supporter d'autres interfaces comme ils sont introduits. Comme nous allons le montrer lorsque nous aborderons nsIClassInfo, certaines factories soutiennent l'interrogation des informations sur la mise en œuvre sous-jacente, comme le langage d'écriture de l'objet dans les interfaces que l'objet prend en charge, etc. Ce genre d' "évolutivité" est un avantage clé qui est dérivé de nsISupports.

XPIDL et bibliothèques de types

Un moyen facile et puissant pour définir une interface - les interfaces dans un environnement de développement multi-plateforme, doit être indépendant du langage - est d'utiliser une interface définition langage(IDL). XPCOM utilise sa propre variante de la définition CORBA OMG Interface Langage (IDL) appelé XPIDL, qui vous permet de spécifier les méthodes, les attributs et les constantes d'une interface donnée, et aussi d'en définir héritage.

Il y a quelques inconvénients à la définition de votre interface à l'aide XPIDL. Il n'y a pas d'héritage multiple possible. Si vous définissez une nouvelle interface, il ne peut pas provenir de plus d'une interface. Une autre limitation des interfaces dans XPIDL est que les noms de méthode doivent être uniques. Vous ne pouvez pas avoir deux méthodes avec le même nom qui prennent des paramètres différents, et la solution de contournement - avec plusieurs noms de fonction - n'est pas joli:

void FooWithInt(in int x);
void FooWithString(in string x);
void FooWithURI(in nsIURI x);

Cependant, ces lacunes sont peu de chose en comparaison des fonctionnalités acquises en utilisant XPIDL. XPIDL vous permet de générer des bibliothèques de types , ou typelibs, qui sont des fichiers avec l'extension .xpt. La bibliothèque de types est une représentation binaire d'une ou plusieurs interfaces. Elle fournit un contrôle programmatique et l'accès à l'interface, ce qui est crucial pour les interfaces utilisées d'autre langages que C++. Lorsque les composants sont accessibles à partir d'autres langages, car ils peuvent être en XPCOM, ils utilisent la bibliothèque de type binaire pour accéder à l'interface, trouver les méthodes supportées, et les appeler. Cet aspect de XPCOM est appelé XPConnect . XPConnect est la couche de XPCOM qui donne accès à des composants XPCOM à partir des langages tels que JavaScript. Voir connexion à des composants de l'interface pour plus d'informations à propos de XPConnect.

Quand un composant est accessible à partir d'une langage autre que C ++, tels que JavaScript, son interface est dit "réfléchi" dans cette langage. Chaque interface réfléchie doit avoir une bibliothèque de type correspondant. Actuellement, vous pouvez écrire des composants en C, C++ ou JavaScript (et parfois Python ou Java, en fonction de l'état des liaisons respectives), et il y a des efforts en cours pour renforcer les liaisons XPCOM pour Ruby et Perl.

Écriture dans d'autres langages

Bien que vous ne disposez pas de l'accès à certains des outils que XPCOM prévoit pour C++ (comme les macros, les modèles, des pointeurs intelligents, et autres) lorsque vous créez des composants dans d'autres langages, vous pouvez être tellement à l'aise avec, que vous pouvez éviter complètement le C++ et construire, par exemple, les composants XPCOM en Python qui peuvent être utilisés à partir de JavaScript, ou vice versa.

Voir les Ressources pour plus d'informations à propos de Python et d'autres langages utilisables avec XPCOM.

Toutes les interfaces publiques en XPCOM sont définies en utilisant la syntaxe de XPIDL. Les bibliothèques de types et les fichiers d'en-tête de C++ sont générés à partir de ces fichiers IDL, et l'outil qui génére ces fichiers est appelé le compilateur xpidl . La section Définir l'interface de WEBLOCK dans XPIDL décrit la syntaxe de XPIDL en détail.

Services de XPCOM

Lorsque les clients utilisent des composants, ils instancient généralement un nouvel objet à chaque fois qu'ils ont besoin de la fonctionnalité du composant fournit. Tel est le cas lorsque, par exemple, les clients travaillent avec des fichiers: chaque fichier séparé est représenté par un objet différent, et plusieurs objets de fichier peut être utilisé à tout moment.

Mais il y a aussi une sorte d'objet connu comme le service , dont il n'y a toujours qu'une seule copie (même si il peut y avoir de nombreux services en cours d'exécution à un moment donné).Chaque fois qu'un client veut accéder à la fonctionnalité fournie par un service, ils parlent à la même instance de ce service. Quand un utilisateur recherche un numéro de téléphone dans une base de données de l'entreprise, par exemple, probablement cette base de données est représentée par un «objet» qui est le même pour tous les collaborateurs. Si ce n'etait pas le cas, l'application aurait besoin de garder deux copies d'une grande base de données en mémoire, pour la même chose, et il pourrait aussi y avoir des incohérences entre les documents si les copies ont divergé.

La fourniture de ce point d'accès unique à la fonctionnalité est mis en oeuvre par le singleton design pattern.

Dans XPCOM, en plus de l'appui et de la gestion des composants, il y a un certain nombre de services qui aident les développeurs à l'écriture de composants. Ces services incluent un fichier abstrait multiplateforme qui offre un accès uniforme et puissant pour les fichiers, les services d'annuaire qui maintiennent l'emplacement application, gestion de la mémoire pour s'assurer que tout le monde utilise le même allocateur de mémoire, et un système de notification d'événement qui permet de passer des messages simples. Le tutoriel va vous montrer l'utilisation de chacun de ces composants et services, et de la Référence de l'API XPCOM avec une liste d'interface complète.

Types XPCOM

Il existe de nombreux types déclarés et de simples macros que nous allons utiliser dans les exemples suivants. La plupart de ces types sont des applications simples. Les types les plus courants sont décrits dans les sections suivantes.

les types de méthode

Ce qui suit est un ensemble de types qui veillent à la convention d'appel correcte et de type de méthodes XPCOM de retour.

NS_IMETHOD Type de retour de déclaration de méthode.
NS_IMETHODIMP Type de retour de mise en œuvre de méthode. 
NS_IMETHODIMP_(type) Cas particulier de type de retour de mise en œuvre. Certaines méthodes telles que AddRef et Release ne renvoient pas le type de retour par défaut.
NS_IMPORT Force la résolution de la méthode en interne par la bibliothèque partagée.
NS_EXPORT Force l'exportation de la méthode par la bibliothèque partagée.

Référence Comptage

Ces macros gérer comptage de référence.

NS_ADDREF Appelle AddRef de nsISupports.
NS_IF_ADDREF Vérifie l'etat null avant d'appeler AddRef.
NS_RELEASE Appelle Release de nsISupports.
NS_IF_RELEASE Vérifie l'etat null avant d'appeler Release.

Codes d'état

Ces macros testent les codes d'état.

NS_FAILED Retourne vrai si le code d'état passé est un échec
NS_SUCCEEDED Retourne vrai est le code d'état passé est un succès.

Variable Mappings

nsrefcnt Type de comptage de référence(entier de 32 bits).
nsresult Type d'erreur par défaut(entier de 32 bits).
nsnull Valeur null par défaut.

Codes d'erreur XPCOM communes

NS_ERROR_NOT_INITIALIZED Instance non initialisée.
NS_ERROR_ALREADY_INITIALIZED Instance déjà initialisée.
NS_ERROR_NOT_IMPLEMENTED Méthode non implémentée
NS_ERROR_NO_INTERFACE Interface non pris en charge.
NS_ERROR_NULL_POINTER Pointeur valide nsnull.
NS_ERROR_FAILURE La méthode a échoué. Erreur générique.
NS_ERROR_UNEXPECTED Erreur inattendue.
NS_ERROR_OUT_OF_MEMORY Allocation de mémoire échouée.
NS_ERROR_FACTORY_NOT_REGISTERED Classe inconnue du registre.

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : Hell_Carlito, SphinxKnight, jmh, Goofy
 Dernière mise à jour par : SphinxKnight,