XPCOM

Implémentation du composant en C++

Implémentation du composant

La compilation de l'IDL a généré un header C++ (MOZILLA/alexis/generated/plop.h) qui contient du code généré à utiliser pour réaliser l'implémentation du composant. Ce header sera, de plus, utilisé pour la compilation.

Il faut tout d'abord écrire le header de la classe correspondant au composant. Nous allons y utiliser des macros se trouvant dans le header généré. Par exemple, la macro NS_DECL_NSIPLOP déclare toutes les méthodes de l'interface.

Nous allons par ailleurs définir les attributs suivants :

Voici le code correspondant :

#include "generated/plop.h"

// 839ca83f-538d-43f6-89dd-fdeccf0e9823
#define PLOP_CID \
{ 0x839ca83f, 0x538d, 0x43f6, { 0x89, 0xdd, 0xfd, 0xec, 0xcf, 0x0e, 0x98, 0x23 } }

#define PLOP_CONTRACTID "@seigneurin.com/Plop_cpp;1"

/* Header file */
class nsPlop : public nsIPlop
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIPLOP

  nsPlop();

private:
  ~nsPlop();

protected:
  /* additional members */
};

Il s'agit ensuite d'écrire l'implémentation des méthodes. Ici aussi, les templates des méthodes peuvent être tirés du fichier généré (MOZILLA/alexis/generated/plop.h).

Lors de l'écriture des méthodes, il faut avant tout prendre garde à ne pas utiliser de fonctions ou de types de données qui soient spécifiques à la plateforme. Il faut donc utiliser la NSPR. Ici, cela se caractérise par l'utilisation de la fonction PR_fprintf en lieu et place de printf.

Voici le code correspondant :

#include "plop.h"
#include <nspr.h>

/* Implementation file */
NS_IMPL_ISUPPORTS1(nsPlop, nsIPlop)

nsPlop::nsPlop()
{
  /* member initializers and constructor code */
  PR_fprintf(PR_STDOUT, " ----- Composant C++: Construction\n");
}

nsPlop::~nsPlop()
{
  /* destructor code */
  PR_fprintf(PR_STDOUT, " ----- Composant C++: Destruction\n");
}

/* void display (in string message); */
NS_IMETHODIMP nsPlop::Display(const char *message)
{
    PR_fprintf(PR_STDOUT, " ----- Composant C++: Appel de 'display' ---> '%s'\n", message);
    return NS_OK;
}

Création d'un module

Il faut ensuite créer le module. Le plus important est le tableau déclarant l'ensemble des composants présents dans le module, en donnant notamment le Class ID et le Contract ID de chaque composant.

Voici la définition du tableau (le code complet du module peut être trouvé sur la page Ressources) :

static const nsModuleComponentInfo components[] =
{
  { "Plop Component", PLOP_CID, PLOP_CONTRACTID, nsPlopConstructor,
    plopRegistrationProc /* NULL if you dont need one */,
    plopUnregistrationProc /* NULL if you dont need one */,
    NULL /* no factory destructor */,
    NULL, //NS_CI_INTERFACE_GETTER_NAME(nsPlop),
    NULL /* no language helper */,
    NULL //&NS_CLASSINFO_NAME(nsPlop)
  }
};

Fichiers et compilation

Les fichiers utilisés sont les suivants :

Il s'agit maintenant de compiler le composant afin de réaliser un bibliothèque chargée dynamiquement (DLL).

Les règles ajoutées au Makefile sont les suivantes :

cpp: libplop.so
	ln -fs $(CURDIR)/$< ../dist/bin/components

plop.o: plop.cpp plop.h generated/plop.h
	g++ -c -I../dist/include/xpcom -I../dist/include/nspr $<
        
plopModule.o: plopModule.cpp generated/plop.h
	g++ -c -I../dist/include/xpcom -I../dist/include/nspr $<
        
libplop.so: plop.o plopModule.o
	g++ -shared -o libplop.so $^ ../dist/lib/libxpcomglue.a  \
	-L/home/alexis/mozilla/dist/lib \
	-lplds4 -lplc4 -lnspr4 -lpthread -ldl -lm

Notons ici que le plus compliqué est de linker avec la NSPR.

A l'issue de la compilation, un lien symbolique sur la DLL est placé dans MOZILLA/dist/bin/components.