OVH Cloud OVH Cloud

Chargement dynamique de plugins/librairies

28 réponses
Avatar
Delf
Bonjour.

Mon application doit charger à l'exécution un ensemble inconnu de
plugins situés dans un répertoire donné.

Ces plugins sont aussi écrits en C++ et implémentent une interface IPlugins.

Je compile les librairies en utilisant la commande suivante :

g++ -shared -I /usr/local/include/libxml2/ -I /usr/local/include/
fichier.cpp -o fichier.so

Ma question, comment récupérer dans le répertoire donné tous les .so,
s'assurer qu'il s'agit bien de plugins (on peut avoir un fichier texte
nommé xxx.so), charger chaque plugins et lancer les méthodes ?

Ca fait beaucoup de questions...

J'ai pu voir dlopen() et extern "C" (mais pour les librairies en C...).

Pour dlopen(), j'utilise le code suivant :

void* handle = dlopen("./plugins/test.so", RTLD_LAZY);

if (handle == NULL)
{
std::cout << dlerror() << std::endl;

exit(1);
}

En sortie : ./plugins/test.so: Undefined symbol "_ZN8IPluginsC2Ev"

Par ailleurs, on m'a dit que dlopen() ne servait pas dans mon cas...
Bref, suis un peu dans le vague.
Merci anticipé.

--
Delf
Do not use this email in Cc!
L'alcool tue lentement. On s'en fout. On n'est pas pressé.

8 réponses

1 2 3
Avatar
Gabriel Dos Reis
"kanze" writes:

[...]

| Si je voulais rester dans l'esprit de la norme C++ (et C), la
| seule façon de faire la conversion serait d'écrire quelque chose
| comme :
|
| void* tmp = dlsym( handle, "my_function" ) ;

je me suis touojours posé la question, pourquoi ne pas définir et
utiliser une union pour dlsym(), de sorte que :

union core {
void* dataptr;
void (*funptr)();
};

core tmp = dlym(handle, "my_function");

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote:
"kanze" writes:

[...]

| Si je voulais rester dans l'esprit de la norme C++ (et C), la
| seule façon de faire la conversion serait d'écrire quelque chose
| comme :

| void* tmp = dlsym( handle, "my_function" ) ;

je me suis touojours posé la question, pourquoi ne pas définir et
utiliser une union pour dlsym(), de sorte que :

union core {
void* dataptr;
void (*funptr)();
};

core tmp = dlym(handle, "my_function");


Par exemple. De bonnes solutions ne manquent pas, en fait. La
bonne solution C++ me semble évident :
void (*fp)() = dlsym< void (*)() >( handle, "my_function" ) ;
Idéalement avec une erreur si le type du symbole dans l'objet ne
correspondait pas. Mais j'ai comme une petite doute que ceux qui
s'occupent de la normalisation d'Unix en seraient d'accord.

Il ne faut pas oublier que dlsym, ce n'est pas Posix -- c'est
X/Open. Que X/Open est un régroupement de vendeurs, et qu'ils
cherchent simplement à normaliser ce qu'ils font en fait -- s'il
y a un groupe où l'innovation n'est pas de jours, c'est bien
chez eux. Et que dlsym existe depuis longtemps ; depuis un
époque où il n'y avait pas de norme C, et que la référence,
c'était le compilateur de la machine où on se trouvait. Le pcc
de Johnson permettait la conversion, et Berkley et System V ont
suivi. (Je ne sais pas exactement quand dlsym est apparu, mais
il était présent dans Sun OS 3 -- une dérivée de Berkley -- en
1988.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
Gabriel Dos Reis wrote:

| > La notion de « conditionally supported » a été inventée à la
| > dernière réunion de Lillehammer.

| Mais où est la différence ? Qu'une implémentation n'est pas
| obligée à documenter qu'elle le supporte ou non ?

L'implémentation est obligée de documenter. Certains voulaient même un
« feature test ». Du moins, c'est l'un des volets qui a nourri le
débat. C'est subtilement assez différent de « implementation define d »


J'aime ce « subtilement assez différent ». C-à-d qu'ils ont
réussi à introduire des différences assez signifiantes sans
qu'on le remarque au premier abord, de façon à se faire pièger ?

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Jean-Marc Bourguet
"kanze" writes:

Gabriel Dos Reis wrote:

| > La notion de « conditionally supported » a été inventée à la
| > dernière réunion de Lillehammer.

| Mais où est la différence ? Qu'une implémentation n'est pas
| obligée à documenter qu'elle le supporte ou non ?

L'implémentation est obligée de documenter. Certains voulaient même un
« feature test ». Du moins, c'est l'un des volets qui a nourri le
débat. C'est subtilement assez différent de « implementation defined »


J'aime ce « subtilement assez différent ». C-à-d qu'ils ont
réussi à introduire des différences assez signifiantes sans
qu'on le remarque au premier abord, de façon à se faire pièger ?


Si j'ai bien compris

implementation defined: l'implementation dit ce qu'elle fait (en
restant parfois dans des limites fixees par la norme)

conditionally supported: du implementation defined ou il n'y a que
deux choix: un comportement du programme ou un diagnostique

Mais j'ai pu mal comprendre. Il faudrait que j'aille voir les
formulations precises.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Delf
Delf wrote:

[...]


Je suis mon p'tit chemin et hop, je suis confronté à un problème conceptuel.

Mes plugins héritent d'une classe CPlugins qui possède des méthodes et
des méthodes pures que doivent obligatoirement implémenter les plugins.

Certains des plugins peuvent fournir une méthode qui sera lancée en fond
de tâche.

Comment déclarer cette méthode afin que le plugins ne soit pas obligé de
l'implémenter et ni CPlugins ? Virtuelle ?

Par ailleurs, comment je pourrais tester si cette méthode de fond de
tâche est disponible ou non ?

Merci d'avance.

--
Delf
Do not use this email in Cc!
On error '051128 19:08:36 mysqld ended', Scuzzo: and that 051128 has no
google, andre: that's the date...

Avatar
Sylvain
Delf wrote on 20/05/2006 17:21:

Mes plugins héritent d'une classe CPlugins qui possède des méthodes et
des méthodes pures que doivent obligatoirement implémenter les plugins.

Certains des plugins peuvent fournir une méthode qui sera lancée en fond
de tâche.

Comment déclarer cette méthode afin que le plugins ne soit pas obligé de
l'implémenter et ni CPlugins ? Virtuelle ?


s'il s'agit simplement de petites taches lancées séquentiellement (et
non de working thread schédulé par un gestionnaire préemptif) pourquoi pas:

class CPlugins {
public:
// ....
abstract void onIdle() {} /* const ou pas */
};

class CDeived : public CPlugins {
public:
// ....
void onIdle() { traitement concret mais pas trop long }
};

ainsi le prog principal itéreta simplement

for (int i = 0; i < nbPlugin; ++i)
plugins[i].onIdle();

Par ailleurs, comment je pourrais tester si cette méthode de fond de
tâche est disponible ou non ?


c'est peut être inutile; si le onIdle est vide (celui de CPlugins) le
temps d'appel est surement négligeable (et sera comparable à un appel à
une méthode d'interrogation virtuelle "bool hasIdlePrcss()").

s'il s'agit de taches lourdes (exécutés par des thread distincts) la
méthode de création du thread sera à la charge du plug-in qui sait s'il
doit ou non créé un tel thread, par exemple:

(en supposant une classe/identifier 'thread', qui dépend de l'OS)

class CPlugins {
public:
// ....
abstract thread getThread() { return null; }
};

class CDerived : public CPlugins {
public:
// ....
thread getThread() {
Thread t = new Thread(???);
return t.getIdent();
}
};

Sylvain.

Avatar
Sylvain
Sylvain wrote on 20/05/2006 19:06:
// ....
abstract void onIdle() {} /* const ou pas */

remplacer tous les 'abstract' par 'virtual' !


Sylvain.

Avatar
Delf
Sylvain wrote:

[...]


Ca répond parfaitement à mes question, merci bien.

--
Delf
Do not use this email in Cc!
On ne va jamais si loin que lorsque l'on ne sait pas où l'on va.

1 2 3