See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: Les Dlls  (Read 1948 times)

0 Members and 1 Guest are viewing this topic.

Offline tofitouf

  • Legend
  • ******
  • Posts: 1380
  • Karma: 0
04 October 2010, 09:33:04
Voici un fil qui peux vous aider à la création de dll.

J'étofferai les premiers posts en fonction de vos différentes questions et commentaires.
Je vais décrire les dll de manière générale et puis les points spécifiques à orbiter.
Le but est de bien comprendre les mécanisme interne

Les Dlls et les librairies statiques

Les dll sont des fichiers qui transportent du code (c et c++ le plus souvent) et qui sont chargées à la volées par un programme tiers. DLL pour dynamic link library.

La différence avec la librairie statique est que justement elle sont chargée au démarrage de l'application et non directement intégré à l'exécutable final.

Quand on crée une lib statique, on obtient juste un .lib qui contient lui aussi du code mais pour l'utiliser dans un autre programme on fait un lien statique et le code contenu dans le .lmib est tranféré dans l'exécutable au moment du linkage (dernière phase de compilation)

l'avantage de la dll est donc de ne pas avoir à modifier l'exécutable pour modifier une partie du programme général. Cela permet également la création de plugin, notion important pour orbiter.

Les librairies statique ont par contre l'avantage d'être justement intégré à l'exe final et donc qu'on ne puisse pas modifier ce code. selon les besoin les deux sont utiles. De plus le linker ne prends dans la lib que ce dont il a besoin. et réduit d'autant la taille de l'exe final. Par exemple si vous avez dans une lib du code qui n'est pas utilisé au final (des classes utiles à d'autres projets) il ne sera pas intégré. Pas besoin de virer ces classes de la compilation, elle le seront toute seule.

Mode de chargement d'un dll

Les dll ont plusieurs manières d'être chargée.

1. Chargement dynamique classique

la plus classique est en "linkant" directement avec le .lib qui est généré en même temps que la dll. Comme avec une librairie statique, la seule différence est que le code n'est pas inclus dans l'exe mais qu'au chargement de ce dernier la dll est demandée également.
Poru trouver al dll windows recherche d'abord à coté de l'exe (dans le même répertoire) et ensuite dans celui du "Path" déclaré dans les variables d'environnement. ce dernier pointe en général dans le répertoire windows et système 32.
mais d'une manière général il faut mieux mettre la dll à coté de l'exe.

2. chargement manuel.

Il est également possible de ne pas "lier" la dll avec l'exe d'origine et de ne la charger qu'au besoin en utilisant des fonctions de chargement. Cette méthode est celle utilisée par tous les systèmes de plugins.

Pour cela l'exe doit faire un

Code: [Select]
HMODULE HandledeMaLib = LoadLibrary("nomdemaDll.dll");
Il récupère alors un pointeur (HMODULE ici) sur la librairie et peux alors retrouver certaines fonctions en utilisant la fonction GetProcAddress.

Cette dernière recherche une fonction (en mode C et pas C++) dans la libraire en utilisant tout simplement son nom.

C'est cette méthode qui est utilisé dans orbiter pour le système de module.

L'api d'orbiter liste toute une série de fonction à implémenter, optionnelles ou non qui permettent de déclarer qu'on a un plugin de vaisseau, de mfd ou de planète (entre autres).

Je ferai la liste plus bas de ces fonctions spécifiques à orbiter en traduisant partiellement le sdk.

La syntaxe des pointeurs de fonctions suit la norme du C et je doit l'avouer est très barbare. J'étofferai cette question si besoin.

----------------------------

La suite au prochain numéro.

vos commentaires sont les bienvenus, mais je les supprimerai surement pour poster quelque chose qui suive directement ce petit cours.



Message modifié ( 04-10-2010 09:47 )

---------------------------------------------

PC en rade, codage en panne.... Nom de Zeus

Offline tofitouf

  • Legend
  • ******
  • Posts: 1380
  • Karma: 0
Reply #1 - 04 October 2010, 09:37:41
------------ en travaux ---------------------------

Créer Des Dlls avec Visual C++

Visual C++ permet la création toute simple de  dll il suffit pour cela de créer un nouveau projet et de spécifier dans la première page des propriétés du projet (Général) comme type de configuration "Bibliothèque dynamique (.dll)"

(les autres choix possibles sont exécutable et librairie statique)

avec cette option visual compilera deux fichiers :
le .dll qui va contenir le code compilé
et le .lib qui va servir à charger cette dll

Comme on l'a vu plus haut il y a plusieurs moyen de charger une dll, et donc plusieur moyen de déclarer les focntions qui seront accessibles depuis l'exe.


Créer Des Dlls qui compilent des classes et fonctions utiles pour divers projets

Pour cela il faut choisir parmi toutes les classes et les fonctions que l'on met dans la dll lesquelles exporter.

Deux mots clefs sont utilisés :
* __declspec( dllimport )  pour l'importation
* __declspec( dllexport ) pour l'exportation

imaginons que l'on veuille exporter un fonction nommée masuperFonction et une classe maClasseDeLaMort

il faut alors écrire dans un .h

Code: [Select]
bool __declspec( dllexport ) masuperFonction(... tout plein de paramètres ici);

class __declspec( dllexport ) maClasseDeLaMort
{
public:
    void uneFonctionQu'onPeuxAppeler();


}


dans les fichiers cpp associé tu met le code de ta fonction comme d'habitude, là rien ne change. Rien à ajouter comme mot clef.

ensuite quand on compile avec visual c++, il génère les 2 fichiers important : la dll et le .lib
si vous voulez distribuer la dll pour être utilisable il faut que tu file le .lib, la dll et le .h ci dessus légèrement modifié.

En effet il faut remplacer dllexport par dllimport.

Comme c'est agaçant de devoir réécrire 2 fois la même chose en changeant un détail il y a une ptite astuce :

Souvent on exporte plusieurs classes, et tout plein de fonctions,
Dans chacune on met un mot clef à la place du __declspec( dllimport )

par exemple  :

Code: [Select]
// fichier maClasseDeLaMort.h

#include "maDll.h"

bool MA_DLL masuperFonction(... tout plein de paramètres ici);
class MA_DLL maClasseDeLaMort
{
.....
}

dans un .h à part (maDll.h par exemple)
inclus par toutes les autres classes (donc souvent en première ligne des autres .h) tu écrit :

Code: [Select]
#ifdef EXPORT_MA_DLL
      #define MA_DLL __declspec( dllexport )
#else
      #define MA_DLL __declspec( dllimport )
#endif

et dans les paramètres de visual (C/C++\Préprocesseur\Définitions du préprocesseur) on ajoute EXPORT_MA_DLL

Et le
tour est joué, la dll générée aura dans sa table 'export toutes les fonctions et les classes qui définissent MA_DLL

Importer le code d'une dll dans mon projet

Les autres projets qui veulent utiliser ta dll eux ne doivent pas définir cette macro.

Quand j'inclus dans un autre projet "maClasseDeLaMort.h", j'inclus alors automatiquement "maDll.h" et donc le bout de code qui fait la définition et le linker sait alors ce code là sera à importer ailleurs.

Pour utiliser la dll il faut aussi importer son .lib associé. pour cela on a plusieurs choix possibles
- soit juste ajouter le .lib dans les fichiers du projet
- soit ajouter ce .lib dans les paramètre visual du projet (Editeur de liens/Entrées/Dépendances supplémentaire)



Message modifié ( 04-10-2010 10:22 )

---------------------------------------------

PC en rade, codage en panne.... Nom de Zeus

Offline tofitouf

  • Legend
  • ******
  • Posts: 1380
  • Karma: 0
Reply #2 - 04 October 2010, 10:20:33
Créer Des Dlls qui implémentent des fonctions spécifiques (cas des plugins d'orbiter)

Le cas des plugins est différent.
En effet comme on l'a vu dans le premier post, l'exe qui charge ses plugins charge la dll manuellement via un LoadLibrary puis recherche les éventuelles fonctions qu'il avait définit avec GetProcAdress.

La liste de ces fonctions est souvent limitée et définit par l'exécutable.
dans notre cas c'est orbiter. Il définit entre autre

* InitModule, ExitModule,
* ovcInit et ovcExit pour les vaisseaux
* opcPreStep appelé à chaque boucle,
* opcPause quand on met en pause,
* opcTimeAccChange quand on chaque l'accélération temporaire
etc etc.

je vous invite à lire le chapitre 7.64 et les suivants de la doc d'orbiter 2010 pour plus de détail pour ces fonctions

Pour les implémenter, il vous suffit de copier la définition précise qui se trouve dans la doc et de les coller dans un fichier .c ou .cpp

ex :

Code: [Select]
DLLCLBK void InitModule(HINSTANCE hmodule)
{
    // mon code d'init ici
}

la macro DLLCLBK est définie par orbiter et vaut
Code: [Select]
extern "C" __declspec (dllexport)
ce qui signifie qu'on exporte cette fonction au format "C"


DllMain, à quoi ca sert ?

La fonction DllMain est une fonction générale de toutes les Dll qui permet de contrôler le chargement déchargement de celle ci.

Les premières version d'orbiter utilisaient ce fonctionnement, mais depuis quelques temps Martin a remplacé ce mécanisme par les fonction InitModule et ExitModule.

Mais ce procédé fonctionne toujours et on retrouve encore pas mal de projet qui l'utilisent pour déclarer leurs plugins


Voici le lien vers la doc Microsoft de la fonction ainsi que toute les valeurs que windows envoie à la dll pour notifier de tous les changements d'état.

http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx

Mais cette fonction n'est pas indispensable, loin de là.

Par défaut visual c++ en génère une si on n'en déclare pas.
Donc à moins de vraiment vouloir tout maitriser il n'est pas nécessaire de s'en préoccuper.



Message modifié ( 04-10-2010 15:13 )

---------------------------------------------

PC en rade, codage en panne.... Nom de Zeus

Offline Thrawn

  • Sr. Member
  • ****
  • Posts: 264
  • Country: France fr
  • Karma: 12
Reply #3 - 04 October 2010, 19:29:50
:wor: :wor: :wor:


------------------------------------------------------------------------------------------------
Ex Astris Scientia

Offline MrSpock

  • Legend
  • ******
  • Posts: 1593
  • Karma: 0
Reply #4 - 04 October 2010, 21:29:56
:wor::wor::wor:


Mr Spock ,
Consultant de VULCAN TECH INDUSTRY.
( et accessoirement chatouilleur de PLAYMOBILS@tm )
http://kenai.com/projects/spacetechs-mecanos

Offline tofitouf

  • Legend
  • ******
  • Posts: 1380
  • Karma: 0
Reply #5 - 05 October 2010, 00:43:28
merci les zamis, et corrigez moi si vous voyez une faute ou si une partie n'est pas bien claire.

Je tenterai de poster ce genre de choses quand je vois d'autres interrogations profondes.
tcho


« Last Edit: 05 October 2010, 01:24:24 by tofitouf »
---------------------------------------------

PC en rade, codage en panne.... Nom de Zeus

Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
Reply #6 - 05 October 2010, 01:24:24
Ça mérite une place avec les tutoriels de Dan. :top:

Je continue ma lecture... :bave:


« Last Edit: 05 October 2010, 01:24:24 by Bibi Uncle »
Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon