Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Linker dynamiquement sans .def

25 réponses
Avatar
Michaël Monerau
Bonjour,

Je cherche à faire un système de "plugin" pour mon programme.
C'est-à-dire que toutes les .dll dans le répertoire "plugins" de mon
prog doivent être chargées, et doivent présenter une interface définie.

Pour cela, dans le programme principal, je fais un LoadLibrary sur
toutes les dlls. Puis, j'appelle GetProcAddress avec les bons arguments.

Actuellement, je n'ai réussi à faire marcher cela que dans un seul cas :
lorsque j'écris un .def à la main pour les dlls plugin qui disent
exactement quelles fonctions doivent être exportées. Là, GetProcAddress
s'y retrouve.

Maintenant, comme il risque d'y avoir pas mal de fonctions à exporter et
à lier ainsi dynamiquement, j'aimerais me passer de l'étape de la
création du .def. Mais même si je mets un "__declspec(dllexport)" devant
les fonctions à exporter, elles ne sont pas reconnues par GetProcAddress
sans le .def pour linker les plugins...

Tout d'abord, est-ce normal ? Si oui, comment puis-je faire pour éviter
d'avoir à écrire le .def à chaque fois (génération auto ?) ? Je subodore
que cela vienne du name mangling, mais j'attends vos
confirmations/infirmations ;-)

--
Michaël << Cortex >> Monerau

10 réponses

1 2 3
Avatar
Manuel Leclerc
Michaël Monerau a écrit :

Je subodore que cela vienne du name mangling, mais
j'attends vos confirmations/infirmations ;-)



A mon avis tu subodores super bien. Utilises un
outils pour voir sous quels noms tes fonctions
sont exportées, et tu ne seras pas déçu du voyage.

Perso, je ne sais pas me passer du point DEF, et
j'attends la "bonne" réponse avec impatience.
Avatar
Quentin Pouplard
Manuel Leclerc wrote:
Michaël Monerau a écrit :

> Je subodore que cela vienne du name mangling, mais
> j'attends vos confirmations/infirmations ;-)

A mon avis tu subodores super bien. Utilises un
outils pour voir sous quels noms tes fonctions
sont exportées, et tu ne seras pas déçu du voyage.

Perso, je ne sais pas me passer du point DEF, et
j'attends la "bonne" réponse avec impatience.



Je subodore la même chose... mais y'a parfois moyen de s'en sortir en ne
laissant qu'une fonction dans le .def qui ne fait que renvoyer une
struct de fonction virtuelle pure (une interface quoi), cependant je
n'ai jamais testé les limites de cette approche sur différent
compilo...

--
Quentin Pouplard (Tene/MyOE)
http://www.myoe.org | http://graff.alrj.org
Avatar
Michaël Monerau
Quentin Pouplard a écrit :

[Problème de Name mangling]

Je subodore la même chose... mais y'a parfois moyen de s'en sortir en ne
laissant qu'une fonction dans le .def qui ne fait que renvoyer une
struct de fonction virtuelle pure (une interface quoi), cependant je
n'ai jamais testé les limites de cette approche sur différent
compilo...



Je vais essayer de mettre cette solution en place. Elle me paraît à la
fois puissante et claire (ça permet de faire un schéma simple et
générique pour documenter, par exemple, la création d'un plugin :
"Faites votre propre Interface dérivée de IPlugin et renvoyez la par
telle fonction").

Je vous tiens au jus ;-)

--
Michaël << Cortex >> Monerau
Avatar
Manuel Leclerc
Michaël Monerau a écrit :

Quentin Pouplard a écrit :

> [Problème de Name mangling]
>
> Je subodore la même chose... mais y'a parfois moyen de
> s'en sortir en ne laissant qu'une fonction dans le .def
> qui ne fait que renvoyer une struct de fonction virtuelle
> pure (une interface quoi), cependant je n'ai jamais testé
> les limites de cette approche sur
> différent compilo...

Je vais essayer de mettre cette solution en place. Elle me
paraît à la fois puissante et claire (ça permet de faire un
schéma simple et générique pour documenter, par exemple, la
création d'un plugin : "Faites votre propre Interface dérivée
de IPlugin et renvoyez la par telle fonction").



Tu ajoutes une couche de complexité avec un avantage que je ne
vois pas. Plus de risque de bug, et puis c'est tout. Quel est
le problème avec le DEF ?
Avatar
Michaël Monerau
Manuel Leclerc a écrit :

Je vais essayer de mettre cette solution en place. Elle me
paraît à la fois puissante et claire (ça permet de faire un
schéma simple et générique pour documenter, par exemple, la
création d'un plugin : "Faites votre propre Interface dérivée
de IPlugin et renvoyez la par telle fonction").




Tu ajoutes une couche de complexité avec un avantage que je ne
vois pas. Plus de risque de bug, et puis c'est tout. Quel est
le problème avec le DEF ?




Je trouve que la solution de l'interface pure est plus sympa à utiliser,
et je me sens plus à l'aise, si j'ai à l'utiliser, face à une interface
qu'il me suffit de copier/coller, puis de modifier, plutôt que si je
dois copier chaque fonction, puis aller dans le .def pour remettre le
nom de chaque fonction. Remarque, c'est vrai que le .def est générique
aussi et peut être copié/collé.

Enfin, finalement, c'est vrai que quand j'y réfléchis, c'est plus pour
une question esthétique (j'évite au maximum de faire des fonctions
seules, pas dans une classe) :)

Pour ce qui est des risques de bugs, je n'en vois pas trop. Une fois que
j'aurai testé, si ça marche, il ne pourra plus rien arriver :p Sinon, je
garderai la méthode du .def.
--
Michaël "Cortex" Monerau
http://www.drag-network.com
Avatar
Quentin Pouplard
Manuel Leclerc wrote:
[snip COM like stuff]

Tu ajoutes une couche de complexité avec un avantage que je ne vois
pas. Plus de risque de bug, et puis c'est tout. Quel est le problème
avec le DEF ?



Je ne suis pas d'accord, on parle de C++ et donc en principe de POO...
et donc tu auras quoi?

côté host: une structure (ou classe) contenant les pointeurs vers les
différentes méthodes (fonctions) exposés par ta DLL, le chargement du
plugin reviendra donc à assigner l'adresse des fonctions aux pointeurs,
en faisant bien attention de pas tout foutre en l'air.

côté client: une série de fonction, très probablement appelant les
méthodes d'une instance de classe gérée par le client.

La "solution" de l'interface (struct de méthode virtuelles pure) permet
de demander à ton compilo de gérer cela, pratiquement le client créera
une classe implémentant l'interface, la seule fonction exposées par la
dll devient donc un truc du genre "return new PluginImplementation();".
Ce qui veut dire: pas de wrapper client, pas d'assignation côté host. Il
me semble que c'est globalement plus efficace. Cela permet également de
faire certaines choses plus facilement, comme par exemple plusieurs
plugins dans la même dll, tu changes la fonctions pour qu'elle renvoie
une liste de pointeur faire des implémentations d'interface... avec une
dll et un .DEF, c'est moins évident.

Cependant, je suis d'accord sur un point: le .DEF n'est a priori pas
problématique, mais il n'est pas vérifié à la compilation, si tu
n'implémentes pas correctement le membre X de ton interface, le compilo
gueule, si ton .DEF ne contient pas la fonction TrucDeLaMort, ça
plantera... au runtime, encore pire, si les arguments de ta fonction ne
sont pas exactement les mêmes, ça pourrait planter à des moments
totalement imprévus (happy debugging... non non, ça n'est pas du vécu
;)

Le seule problème (well, l'un des seuls ;) de cette méthode, comme je
l'ai dit, c'est que je ne l'ai pratiqué qu'en utilisant un seul compilo
(VC6 à l'époque), mais à priori, vu que la plupart des compilo se
mappent sur COM je pense que ça ne posera pas de problème...

--
Quentin Pouplard (Tene/MyOE)
http://www.myoe.org | http://graff.alrj.org
Avatar
Manuel Leclerc
Quentin Pouplard a écrit :

Manuel Leclerc wrote:

> [snip COM like stuff]
>
> Tu ajoutes une couche de complexité avec un avantage que je
> ne vois pas. Plus de risque de bug, et puis c'est tout. Quel
> est le problème avec le DEF ?

Je ne suis pas d'accord, on parle de C++ et donc en principe de
POO...
et donc tu auras quoi?

[...]



Ha mais moi j'avais pas compris que c'était du C++/OO/COM/toussa.

Si je devais définir une architecture de plugin pour un de
mes logiciels, je limiterais l'emploi de COM aux cas où je
ne pourais vraiment pas faire autrement (pour le lien avec
un langage de script dans une page web par exemple) et pour
tout le reste je ferais des fonctions C classiques. Chacun
son truc. Moi, c'est "moins il y a de COM, moins il y a
de bug". Tu fais un objet COM quand tu veux que ton code
soit utilisable un peu n'importe où. Pour une architecture
de plugin, tu veux pouvoir utiliser le code des autres, c'est
pas pareil.
Avatar
Quentin Pouplard
Manuel Leclerc wrote:
Quentin Pouplard a écrit :

> Manuel Leclerc wrote:
>
> > [snip COM like stuff]
> >
> > Tu ajoutes une couche de complexité avec un avantage que je ne
> > vois pas. Plus de risque de bug, et puis c'est tout. Quel est le
> > problème avec le DEF ?
>
> Je ne suis pas d'accord, on parle de C++ et donc en principe de
> POO...
> et donc tu auras quoi?
>
> [...]

Ha mais moi j'avais pas compris que c'était du C++/OO/COM/toussa.



Ce n'est pas du COM, mais du COM like, COM repose sur les mêmes
concepts, la grosse différence est que la dll n'expose pas une fonction
qui crée l'instance mais ce mécanisme est en partie pris en charge par
l'architecture COM, via entre autre la base de registre.

Si je devais définir une architecture de plugin pour un de mes
logiciels, je limiterais l'emploi de COM aux cas où je ne pourais
vraiment pas faire autrement (pour le lien avec un langage de script
dans une page web par exemple) et pour tout le reste je ferais des
fonctions C classiques. Chacun son truc. Moi, c'est "moins il y a de
COM, moins il y a de bug". Tu fais un objet COM quand tu veux que ton
code soit utilisable un peu n'importe où. Pour une architecture de
plugin, tu veux pouvoir utiliser le code des autres, c'est pas
pareil.



?? Je ne te suis pas, le rapport entre COM et bug? Tu fais des fonctions
C classique en cas de POO? Tu pense que tu feras un programme plus
robuste en C sans objet qu'en C++ avec la prog objet? Le problème de
name mangling est du au fait qu'il n'y a pas de standard de décoration
en C++... il faut donc en "choisir" un... autant prendre ce que t'offre
ton compilo, non?


--
Quentin Pouplard (Tene/MyOE)
http://www.myoe.org | http://graff.alrj.org
Avatar
Manuel Leclerc
Quentin Pouplard a écrit :

Manuel Leclerc wrote:

> Ha mais moi j'avais pas compris que c'était
> du C++/OO/COM/toussa.

Ce n'est pas du COM, mais du COM like, COM repose
sur les mêmes concepts, la grosse différence est que
la dll n'expose pas une fonction qui crée l'instance
mais ce mécanisme est en partie pris en charge par
l'architecture COM, via entre autre la base de registre.



COM like, ça ne veut rien dire. COM ça commence avec
QueryInterface, AddRef, Release et derrière tu as une
pelote de 3 kilomètres.

> Si je devais définir une architecture de plugin pour
> un de mes logiciels, je limiterais l'emploi de COM aux
> cas où je ne pourrais vraiment pas faire autrement (pour
> le lien avec un langage de script dans une page web par
> exemple) et pour tout le reste je ferais des fonctions C
> classiques. Chacun son truc. Moi, c'est "moins il y a de
> COM, moins il y a de bug". Tu fais un objet COM quand tu
> veux que ton code soit utilisable un peu n'importe où.
> Pour une architecture de plugin, tu veux pouvoir utiliser
> le code des autres, c'est pas pareil.

?? Je ne te suis pas, le rapport entre COM et bug ?



Le rapport, c'est les MFC, ATL et tout le bataclan. Les
modèles de threading, le multi-process et tout le reste.
C'est très compliqué, avec beaucoup de puissance "cachée",
donc plein de gâchettes sensibles qui ne demandent qu'à
t'envoyer une balle dans le pied.

Tu fais des fonctions C classique en cas de POO ?



Je fais des fonctions C classiques quand je veux
interfacer un EXE avec des DLLs qui seront écrites
par je ne sais qui dans je ne sais quel langage.
On parlait de plugin, non ?

Tu penses que tu feras un programme plus robuste en
C sans objet qu'en C++ avec la prog objet ?



Je pense que la plupart des programmes que j'écris
en ayant une complète liberté n'ont pas besoin de POO.
Je pense aussi que C++ est un langage encore plus merdique
que C pour ce qui est de la facilité DECONCERTANTE avec
laquelle on peut écrire un programme truffé de bug.
A part ça, j'adore le C, c'est mon langage préféré, et
j'aime bien faire un peu de C++ de temps en temps, ça
change.

Le problème de name mangling est du au fait qu'il n'y a pas
de standard de décoration en C++... il faut donc en "choisir"
un... autant prendre ce que t'offre ton compilo, non?



Non. Pour moi une DLL, c'est WINAPI et export en DEF, et elle
pourra être utilisée à peu prêt normalement n'importe où.
Avatar
Quentin Pouplard
Manuel Leclerc wrote:
> Tu penses que tu feras un programme plus robuste en
> C sans objet qu'en C++ avec la prog objet ?

Je pense que la plupart des programmes que j'écris
en ayant une complète liberté n'ont pas besoin de POO.



Tu as bien de la chance ;) Ou plutôt non, c'est marrant l'objet...

--
Quentin Pouplard (Tene/MyOE)
http://www.myoe.org | http://graff.alrj.org
1 2 3