OVH Cloud OVH Cloud

contenu d'une dll

7 réponses
Avatar
Olivier Ravard
Bonjour à tous,

Voici ma question de débutant sous windows...

Il a t-il un moyen de charger une librairie dll après le
chargement de l'application ?
Y a t-il un moyen en C++ de connaitre la liste des classes
implémentées dans cette librairie et d'instancier des
objets décrits par ces classes sachant que les prototypes
des fonctions ne sont pas disponibles lors de la compilation
de l'application ?

Si je ne suis pas clair, voici mon objectif :
Je souhaite qu'un utilisateur de mon application puisse ajouter
un module (sous forme dll) pour que l'application en question
puisse créer de noveaux objets sans recompilation.

O.R.

7 réponses

Avatar
Fabien SK
Olivier Ravard wrote:
Voici ma question de débutant sous windows...
Il a t-il un moyen de charger une librairie dll après le
chargement de l'application ?
fr.comp.os.ms-windows.programmation est plus approprié

Oui, mais sur ce groupe on parle de tout ce qui est C++ standard.

implémentées dans cette librairie et d'instancier des
On ne dit pas "librairie" mais "bibliothèque", ou alors "library" (avec

l'accent :-) ) si on aime les anglicismes.

Avatar
Benoit Rousseau
Olivier Ravard wrote:
Bonjour à tous,

Voici ma question de débutant sous windows...

Il a t-il un moyen de charger une librairie dll après le
chargement de l'application ?
Je n'en sais rien : tu trouveras surement une reponse sur

fr.comp.os.ms-windows.programmation

Y a t-il un moyen en C++ de connaitre la liste des classes
implémentées dans cette librairie et d'instancier des
objets décrits par ces classes sachant que les prototypes
des fonctions ne sont pas disponibles lors de la compilation
de l'application ?

Si je ne suis pas clair, voici mon objectif :
Je souhaite qu'un utilisateur de mon application puisse ajouter
un module (sous forme dll) pour que l'application en question
puisse créer de noveaux objets sans recompilation.


Ce que je fais, je crée une "interface" de plug-in :
class PlugIn {
...
};

et chaque dll doit implementer cette class ainsi qu'une fonction
retournant une nouvelle instance de cette classe :
class MyPlugIn : public PlugIn { ... };
PlugIn* create_plugin( ) {
PlugIn* to_return = new MyPlugIn;
...
return to_return;
}

Lorsque tu charges ta bibliothèque, tu charges aussi la fonction et
appelles ton createur de plugin.

Utilisant mes plugins pour les librairies graphiques comme GTK (qui
demande a tourner de son côté), je lance en général les plugins dans des
threads.

--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Frédéri MIAILLE
"Olivier Ravard" a écrit dans le message de
news:bodcv8$qpk$
Bonjour à tous,

Voici ma question de débutant sous windows...

Il a t-il un moyen de charger une librairie dll après le
chargement de l'application ?
Oui.


Y a t-il un moyen en C++ de connaitre la liste des classes
implémentées dans cette librairie et d'instancier des
objets décrits par ces classes sachant que les prototypes
des fonctions ne sont pas disponibles lors de la compilation
de l'application ?
S'ils ne sont pas disponibles, c'est que ce n'est pas prévu pour être

utilisé par ailleurs.

Si je ne suis pas clair, voici mon objectif :
Je souhaite qu'un utilisateur de mon application puisse ajouter
un module (sous forme dll) pour que l'application en question
puisse créer de noveaux objets sans recompilation.
Euh, ton application principale doit quand même connaître les types des

objets or si un nouveau type existe dans la DLL, tu n'y coupes pas, tu es
obligé de le connaître dans le programme principal. Que tu récupères une
instance ou un type.
En revanche, c'est possible si les signatures sont les mêmes et que juste
les sémantiques changent.

Par contre, je pense que c'est limite hors sujet.

--
Frédéri MIAILLE
fr.comp.lang.c
fr.comp.lang.c++
fr.comp.os.ms-windows.programmation
fr.comp.graphisme.programmation

Avatar
kanze
Olivier Ravard wrote in message
news:<bodcv8$qpk$...

Voici ma question de débutant sous windows...

Il a t-il un moyen de charger une librairie dll après le
chargement de l'application ?


Ça dépend du système. J'imagine en fait que si un système offre la
possibilité d'une édition de liens dynamique, il offre la possibilité
de
le faire explicitement.

Mon expérience est surtout avec Unix, mais un survol rapide de la
documentation Windows
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/about_dynamic_link_libraries.asp)
donne l'impréssion qu'il lui ressemble rémarquablement, même jusqu'à
la
façon incroyablement stupide de revoyer l'information sur les erreurs.

Une chose à laquelle il faut faire attention. Sous Unix, et
probablement
sous les autres systèmes aussi, quand tu veux chercher l'adresse d'un
symbole dans l'objet chargé, il faut donné le nom tel qu'il apparaît
dans la table des symboles, et non tel que tu l'as écrit dans ton
programme. Surtout en C++, à cause de la décoration. Sous Solaris, au
moins, il suffit que je déclare la fonction « extern "C" », et je peux
utiliser le nom tel quel ; je n'ai pas encore essayé sous Windows.

Y a t-il un moyen en C++ de connaitre la liste des classes
implémentées dans cette librairie et d'instancier des
objets décrits par ces classes sachant que les prototypes
des fonctions ne sont pas disponibles lors de la compilation
de l'application ?

Si je ne suis pas clair, voici mon objectif :

Je souhaite qu'un utilisateur de mon application puisse ajouter
un module (sous forme dll) pour que l'application en question
puisse créer de noveaux objets sans recompilation.


La solution que j'utilise, c'est de définir des classes abstraites de
base, dont l'utilisateur doit hériter, ainsi qu'une fabrique abstraite
pour les créer et une fonction « extern "C" » qui renvoie l'adresse de
cette fabrique. L'utilisateur définit les classes dérivées, et la
fabrique dérivée qui les crée, ainsi que quelque chose du genre :

extern "C" AbstractFactory*
createFactory()
{
static ConcreteDerivedFactory theOneAndOnly ;
return &theOneAndOnly ;
}

C'est le seul point d'entrée dont on a besoin.

Mais je crois ici qu'on tombe sur des différences entre les deux
systèmes. Sous Unix, la visibilité des symboles dans l'objet linké
dynamiquement dépend des paramètres de dlopen ; du peu que j'ai
entendu,
sous Windows, c'est plutôt defini lors de la création de l'objet
dynamique, au moyen des extensions du langage, et peut-être aussi des
options du compilateur et de l'éditeur de liens.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Loïc Joly
wrote:
Olivier Ravard wrote in message
news:<bodcv8$qpk$...


Une chose à laquelle il faut faire attention. Sous Unix, et
probablement
sous les autres systèmes aussi, quand tu veux chercher l'adresse d'un
symbole dans l'objet chargé, il faut donné le nom tel qu'il apparaît
dans la table des symboles, et non tel que tu l'as écrit dans ton
programme. Surtout en C++, à cause de la décoration. Sous Solaris, au
moins, il suffit que je déclare la fonction « extern "C" », et je peux
utiliser le nom tel quel ; je n'ai pas encore essayé sous Windows.


C'est bien le cas.


Mais je crois ici qu'on tombe sur des différences entre les deux
systèmes. Sous Unix, la visibilité des symboles dans l'objet linké
dynamiquement dépend des paramètres de dlopen ; du peu que j'ai
entendu,
sous Windows, c'est plutôt defini lors de la création de l'objet
dynamique, au moyen des extensions du langage, et peut-être aussi des
options du compilateur et de l'éditeur de liens.


Effectivement, if faut explicitement exporter tous les symboles qui
peuvent être utilisés dans la DLL. A noter que .NET introduit des
nouveaux concepts de DLL avec des possibilités accrues (fonctions
d'introspection, export "propre" de classe, "déclaration" incluse dans
la DLL...), dont je ne parle pas ici.

Une autre différence que je trouve importante, c'est que sous windows,
une DLL ne peut pas appeler (ou du moins pas simplement) une fonction
définie dans le programme de base (je crois que sur certains unix, c'est
possible).

--
Loïc

Avatar
kanze
Loïc Joly wrote in message
news:<bogu0e$bai$...
wrote:
Olivier Ravard wrote in message
news:<bodcv8$qpk$...

Une chose à laquelle il faut faire attention. Sous Unix, et
probablement sous les autres systèmes aussi, quand tu veux chercher
l'adresse d'un symbole dans l'objet chargé, il faut donné le nom tel
qu'il apparaît dans la table des symboles, et non tel que tu l'as
écrit dans ton programme. Surtout en C++, à cause de la décoration.
Sous Solaris, au moins, il suffit que je déclare la fonction «
extern "C" », et je peux utiliser le nom tel quel ; je n'ai pas
encore essayé sous Windows.


C'est bien le cas.


C'est bien le cas que ça marche sous Windows, ou c'est bien le cas que
Windows est différent. Après avoir poster, à titre de curiosité
personnelle, j'ai essayé sous Windows ; je n'ai pas réussi à le faire
marcher. Un collègue qui travaille sous Windows m'a dit qu'il faut soit
une déclaration spéciale (extension du langage), soit un fichier spécial
(.def, ou quelque chose de semblable) pour dire à l'éditer de liens
quels symboles exporter.

Mais je crois ici qu'on tombe sur des différences entre les deux
systèmes. Sous Unix, la visibilité des symboles dans l'objet linké
dynamiquement dépend des paramètres de dlopen ; du peu que j'ai
entendu, sous Windows, c'est plutôt defini lors de la création de
l'objet dynamique, au moyen des extensions du langage, et peut-être
aussi des options du compilateur et de l'éditeur de liens.


Effectivement, if faut explicitement exporter tous les symboles qui
peuvent être utilisés dans la DLL.


J'avoue ne pas comprendre pourquoi. Mais je ne vois pas que ça pose un
problème non plus ; j'imagine que dans la plupart du cas d'un chargement
explicite, on fait à peu près ce que j'ai expliqué, avec une fabrique
abstraite, et qu'il n'y aurait qu'un seul symbole à exporter.

Dans les rares cas où on veut un chargement dynamique d'un ensemble de
fonctions, ça pourrait être embêtant, peut-être.

Mais ce n'est pas sans avantages non plus -- sous Unix, on compte sur
l'utilisateur de faire l'édition de liens avec les symboles en local, et
s'il oublie, on cour la risque des conflits.

A noter que .NET introduit des nouveaux concepts de DLL avec des
possibilités accrues (fonctions d'introspection, export "propre" de
classe, "déclaration" incluse dans la DLL...), dont je ne parle pas
ici.

Une autre différence que je trouve importante, c'est que sous windows,
une DLL ne peut pas appeler (ou du moins pas simplement) une fonction
définie dans le programme de base (je crois que sur certains unix,
c'est possible).


Alors, comment fait-il pour malloc ? Est-ce qu'il y a une copie de
malloc par DLL ? Et si ça vaut pour les fonctions, qu'est-ce qui se
passe pour les symboles -- malloc a besoin des variables statiques, et
s'il y en a plusieurs copies d'elles, ça ne marche pas.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
Arnaud Debaene
wrote:

Une autre différence que je trouve importante, c'est que sous
windows, une DLL ne peut pas appeler (ou du moins pas simplement)
une fonction définie dans le programme de base (je crois que sur
certains unix, c'est possible).


Alors, comment fait-il pour malloc ? Est-ce qu'il y a une copie de
malloc par DLL ? Et si ça vaut pour les fonctions, qu'est-ce qui se
passe pour les symboles -- malloc a besoin des variables statiques, et
s'il y en a plusieurs copies d'elles, ça ne marche pas.


Deux solutions:
- soit chaque module (exe et dll) embarque sa propre version (linkée
statiquement) de la CRT. Ca implique qu'un morceau de mémoire alloué dans un
module ne peut pas être désalloué dans un autre module.
- soit (solution préférée) tous les modules sont liés à une version DLL de
la CRT (plus ou moins l'équivalent de libc.so sous Linux).

Au passage, bien que ce ne soit pas supporté officiellement, il est possible
à grands coup de hack ignobles dans le format PE d'exporter des symboles
depuis un executable sous Windows. C'est ce que fait Matlab par exemple (
pour raisons de compatiblité avec *nix j'imagine).

Arnaud