IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Bibliothèques dynamiques et RAII


Sujet :

C++

  1. #1
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut Bibliothèques dynamiques et RAII
    Bonjour,
    Je dois utiliser des bibliothèques dynamiques dans un projet, et j'aimerais avoir des conseils pour le faire proprement.

    Première chose, histoire de limiter les risques de fuites mémoire, j'ai réalisé un wrapper pour la gestion des bibliothèques, avec la classe d'exception qui va bien.
    Chaque objet gère un descripteur de bibliothèque, et la fonction « dlclose() » est appelée quoi qu'il arrive.
    Bon, ça existe peut-être déjà, mais pas dans le standard (enfin pas à ma connaissance…), et puis c'est tellement compliqué à faire…
    Bref, tout ça fonctionne, le problème n'est pas là.

    En fait, le nombre de bibliothèques à charger peut varier énormément d'une exécution à l'autre, ainsi que les symboles à chercher.
    Et c'est impossible à prévoir l'avance.
    Il peut même arriver qu'aucune bibliothèque ne soit chargée.
    De plus, on ne sait pas dans quelle bibliothèque particulière chercher chaque symbole ; tout ce que l'on connaît, c'est leur type.

    S'il faut se coltiner tous les descripteurs, même avec mon wrapper, ça peut vite devenir lourd…
    Donc il faudrait une interface qui permette de gérer de manière transparente les bibliothèques chargées.

    On peut penser à une classe où chaque instance est en réalité une collection des objets pré-cités, ou même simplement une collection de descripteurs.
    Mais étant donné que l'on travaille avec toutes les bibliothèques chargées, ça ne me paraît pas cohérent (correct ?) d'avoir la possibilité de créer plusieurs instances.
    Ou alors, il faut utiliser le design pattern « singleton ».

    Ceci dit, d'un point de vue extérieur à la classe, donner la responsabilité de l'ouverture des bibliothèques, de leur fermeture, et de la recherche des symboles à un objet me paraît étrange, pas très naturelle/intuitive.
    Je ne saurais exprimer exactement pourquoi…
    Je verrais plutôt une classe qui ne fournit (avec une visibilité publique) que des fonctions membres statiques.

    Alors, avant même de s'intéresser à des questions d'implémentation, quel est votre sentiment à ce sujet ?
    Verriez-vous plutôt un singleton ou une classe non instanciable pour remplir ce rôle ? (et pourquoi ? )
    Ou autre chose ?

    Je vous remercie d'avance pour les nombreuses remarques que vous allez laisser , et que je ne manquerai pas de lire avec attention.

  2. #2
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Hum, ça n'a pas l'air de beaucoup vous inspirer…
    Bon, en attendant, je vais poster mes codes source.
    Avec un peu de chance, les critiques qui en découleront m'aideront à trouver une réponse à ma question…
    Je les ai testés, il fonctionnent, et ne provoquent pas de fuite mémoire ; enfin mise à part celle signalée dans un précédent sujet

    Tout d'abord, les classes d'exception utilisées :
    dynamic_library_error.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     1| #ifndef DYNAMIC_LIBRARY_ERROR_HPP
     2| #define DYNAMIC_LIBRARY_ERROR_HPP
     3| 
     4| 
     5| #include <stdexcept>                // for std::runtime_error
     6| #include <string>
     7| 
     8| 
     9| 
    10| class DynamicLibraryError : public std::runtime_error
    11| {
    12| 
    13|     public:
    14|         explicit
    15|         DynamicLibraryError(const std::string& msg)
    16|          : std::runtime_error("dlerror: " + msg)
    17|         {}
    18| 
    19| }; // class DynamicLibraryError
    20| 
    21| 
    22| 
    23| 
    24| 
    25| 
    26| 
    27| 
    28| class DynamicLibraryCloseError : public DynamicLibraryError
    29| {
    30| 
    31|     public:
    32|         explicit
    33|         DynamicLibraryCloseError(const std::string& msg)
    34|          : DynamicLibraryError(msg)
    35|         {}
    36| 
    37| }; // class DynamicLibraryError
    38| 
    39| 
    40| 
    41| #endif // DYNAMIC_LIBRARY_ERROR_HPP
    Ensuite, le wrapper que j'ai brièvement évoqué.
    Je renvoie ceux qui trouveraient ma fonction de recherche de symbole étrange à la documentation de « dlsym() » (ici, je ne sais pas a priori si l'utilisateur cherche une variable/constante ou une fonction).
    dynamic_library_handle.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
      1| #ifndef DYNAMIC_LIBRARY_HANDLE_HPP
      2| #define DYNAMIC_LIBRARY_HANDLE_HPP
      3| 
      4| 
      5| #include <stdexcept>                        // for std::runtime_error
      6| #include <string>
      7| 
      8| #include <dlfcn.h>
      9| 
     10| #include "dynamic_library_error.hpp"
     11| 
     12| 
     13| 
     14| class DynamicLibraryHandle
     15| {
     16| 
     17| 
     18| //******************************* NESTED TYPES *******************************//
     19| 
     20|     public:
     21|         enum OpenMode {Lazy = RTLD_LAZY, Now = RTLD_NOW};
     22| 
     23|         enum Flag {Global = RTLD_GLOBAL,
     24|                    Local = RTLD_LOCAL,
     25|                    NoDelete = RTLD_NODELETE,
     26|                    NoLoad = RTLD_NOLOAD,
     27|                    DeepBind = RTLD_DEEPBIND};
     28| 
     29| #ifdef _GNU_SOURCE
     30|         enum PseudoHandle {Default, Next};
     31| #endif
     32| 
     33| 
     34| 
     35| //************************** STATIC MEMBER VARIABLES *************************//
     36| 
     37| #ifdef _GNU_SOURCE
     38|     private:
     39|         static
     40|         const DynamicLibraryHandle _default;
     41| 
     42|         static
     43|         const DynamicLibraryHandle _next;
     44| #endif
     45| 
     46| 
     47| //***************************** MEMBER VARIABLES *****************************//
     48| 
     49|     private:
     50|         void *_opaqueHandle;
     51| 
     52| #ifdef _GNU_SOURCE
     53|         bool _pseudoHandle;
     54| #endif
     55| 
     56| 
     57| 
     58| //************************** STATIC MEMBER FUNCTIONS *************************//
     59| 
     60| #ifdef _GNU_SOURCE
     61|     public:
     62|         template <typename SymbolType>
     63|         static
     64|         SymbolType searchSymbol(PseudoHandle __ph, const std::string& symbol)
     65|         throw(DynamicLibraryError);
     66| 
     67|         static
     68|         const DynamicLibraryHandle& pseudoHandle(PseudoHandle __ph) throw();
     69| #endif
     70| 
     71| 
     72| //******************************* CONSTRUCTORS *******************************//
     73| 
     74|     public:
     75|         DynamicLibraryHandle() throw() : _opaqueHandle()
     76| #ifdef _GNU_SOURCE
     77|         , _pseudoHandle(false)
     78| #endif
     79|         {}
     80| 
     81|         explicit inline
     82|         DynamicLibraryHandle(OpenMode mode, int flags = 0)
     83|         throw(DynamicLibraryError);
     84| 
     85|         inline
     86|         DynamicLibraryHandle(const std::string& filename,
     87|                              OpenMode mode,
     88|                              int flags = 0)
     89|         throw(DynamicLibraryError);
     90| 
     91|     private:
     92| #ifdef _GNU_SOURCE
     93|         DynamicLibraryHandle(void *pseudoHandle) throw()
     94|          : _opaqueHandle(pseudoHandle), _pseudoHandle(true)
     95|         {}
     96| #endif
     97| 
     98|         DynamicLibraryHandle(const DynamicLibraryHandle&);
     99| 
    100| 
    101| //******************************** DESTRUCTOR ********************************//
    102| 
    103|     public:
    104|         ~DynamicLibraryHandle() throw();
    105| 
    106| 
    107| //********************************** GETTERS *********************************//
    108| 
    109|         inline
    110|         bool isOpened() const throw();
    111| 
    112| #ifdef _GNU_SOURCE
    113|         inline
    114|         bool isPseudoHandler() const throw();
    115| #endif
    116| 
    117| 
    118| //********************************* OPERATORS ********************************//
    119| 
    120|     private:
    121|         DynamicLibraryHandle& operator = (const DynamicLibraryHandle&);
    122| 
    123| 
    124| //************************** OTHER MEMBER FUNCTIONS **************************//
    125| 
    126|         void open(const char *filename, int flags) throw(DynamicLibraryError);
    127| 
    128|     public:
    129|         inline
    130|         void open(OpenMode mode, int flags = 0) throw(DynamicLibraryError);
    131| 
    132|         inline
    133|         void open(const std::string& filename, OpenMode mode, int flags = 0)
    134|         throw(DynamicLibraryError);
    135| 
    136|         void close() throw(DynamicLibraryCloseError);
    137| 
    138|         template <typename SymbolType>
    139|         SymbolType searchSymbol(const std::string& symbol) const
    140|         throw(std::runtime_error, DynamicLibraryError);
    141| 
    142|         void swap(DynamicLibraryHandle& other) throw();
    143| 
    144| 
    145| }; // class DynamicLibraryHandle
    146| 
    147| 
    148| 
    149| 
    150| 
    151| //************************** STATIC MEMBER FUNCTIONS *************************//
    152| 
    153| 
    154| #ifdef _GNU_SOURCE
    155| 
    156| template <typename SymbolType>
    157| SymbolType DynamicLibraryHandle::searchSymbol(PseudoHandle __ph, const std::string& symbol)
    158| throw(DynamicLibraryError)
    159| {
    160|     return pseudoHandle(__ph).searchSymbol<SymbolType>(symbol);
    161| }
    162| 
    163| #endif
    164| 
    165| 
    166| 
    167| //******************************* CONSTRUCTORS *******************************//
    168| 
    169| 
    170| inline
    171| DynamicLibraryHandle::DynamicLibraryHandle(OpenMode mode, int flags) throw(DynamicLibraryError)
    172|  : _opaqueHandle()
    173| #ifdef _GNU_SOURCE
    174|    , _pseudoHandle(false)
    175| #endif
    176| {
    177|     open(mode, flags);
    178| }
    179| 
    180| 
    181| inline
    182| DynamicLibraryHandle::DynamicLibraryHandle(const std::string& filename, OpenMode mode, int flags)
    183| throw(DynamicLibraryError)
    184|  : _opaqueHandle()
    185| #ifdef _GNU_SOURCE
    186|    , _pseudoHandle(false)
    187| #endif
    188| {
    189|     open(filename, mode, flags);
    190| }
    191| 
    192| 
    193| 
    194| //********************************** GETTERS *********************************//
    195| 
    196| 
    197| inline
    198| bool DynamicLibraryHandle::isOpened() const throw()
    199| {
    200|     return (_opaqueHandle != NULL);
    201| }
    202| 
    203| 
    204| #ifdef _GNU_SOURCE
    205| 
    206| inline
    207| bool DynamicLibraryHandle::isPseudoHandler() const throw()
    208| {
    209|     return _pseudoHandle;
    210| }
    211| 
    212| #endif
    213| 
    214| 
    215| 
    216| //************************** OTHER MEMBER FUNCTIONS **************************//
    217| 
    218| 
    219| inline
    220| void DynamicLibraryHandle::open(OpenMode mode, int flags) throw(DynamicLibraryError)
    221| {
    222|     return open(NULL, mode | flags);
    223| }
    224| 
    225| inline
    226| void DynamicLibraryHandle::open(const std::string& filename, OpenMode mode, int flags)
    227| throw(DynamicLibraryError)
    228| {
    229|     return open(filename.c_str(), mode | flags);
    230| }
    231| 
    232| 
    233| template <typename SymbolType>
    234| SymbolType DynamicLibraryHandle::searchSymbol(const std::string& symbol) const
    235| throw(std::runtime_error, DynamicLibraryError)
    236| {
    237| #ifdef _GNU_SOURCE
    238|     if (!_pseudoHandle) {
    239| #endif
    240| 
    241|         if (!_opaqueHandle)
    242|             throw std::runtime_error("No loaded dynamic library.");
    243| 
    244| #ifdef _GNU_SOURCE
    245|     }
    246| #endif
    247| 
    248|     dlerror();
    249| 
    250|     SymbolType ret;
    251|     *reinterpret_cast<void **>( &ret ) = dlsym(_opaqueHandle, symbol.c_str());
    252| 
    253|     char *error = dlerror();
    254|     if (error)
    255|         throw DynamicLibraryError(error);
    256| 
    257|     return ret;
    258| }
    259| 
    260| 
    261| 
    262| //*************************** NON-MEMBER FUNCTIONS ***************************//
    263| 
    264| 
    265| inline
    266| void swap(DynamicLibraryHandle& x, DynamicLibraryHandle& y) throw()
    267| {
    268|     return x.swap(y);
    269| }
    270| 
    271| 
    272| 
    273| #endif // DYNAMIC_LIBRARY_HANDLE_HPP
    dynamic_library_handle.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
      1| #include "dynamic_library_handle.hpp"
      2| 
      3| 
      4| 
      5| 
      6| //************************** STATIC MEMBER VARIABLES *************************//
      7| 
      8| 
      9| #ifdef _GNU_SOURCE
     10| 
     11| const DynamicLibraryHandle
     12| DynamicLibraryHandle::_default(RTLD_DEFAULT);
     13| 
     14| 
     15| const DynamicLibraryHandle
     16| DynamicLibraryHandle::_next(RTLD_NEXT);
     17| 
     18| #endif
     19| 
     20| 
     21| 
     22| 
     23| //************************** STATIC MEMBER FUNCTIONS *************************//
     24| 
     25| 
     26| #ifdef _GNU_SOURCE
     27| 
     28| const DynamicLibraryHandle&
     29| DynamicLibraryHandle::pseudoHandle(PseudoHandle __ph) throw()
     30| {
     31|     switch (__ph) {
     32|         case Next:
     33|             return _next;
     34| 
     35|         default:
     36|             return _default;
     37|     }
     38| }
     39| 
     40| #endif
     41| 
     42| 
     43| 
     44| //******************************** DESTRUCTOR ********************************//
     45| 
     46| 
     47| DynamicLibraryHandle::~DynamicLibraryHandle() throw()
     48| {
     49|     try {
     50|         close();
     51|     }
     52|     catch (const DynamicLibraryCloseError&) {
     53|         _opaqueHandle = NULL;
     54|     }
     55| }
     56| 
     57| 
     58| 
     59| //************************** OTHER MEMBER FUNCTIONS **************************//
     60| 
     61| 
     62| void DynamicLibraryHandle::open(const char *filename, int flags) throw(DynamicLibraryError)
     63| {
     64| #ifdef _GNU_SOURCE
     65|     if (!_pseudoHandle) {
     66| #endif
     67| 
     68|         if (_opaqueHandle)
     69|             close();
     70| 
     71|         _opaqueHandle = dlopen(filename, flags);
     72|         if (!_opaqueHandle)
     73|             throw DynamicLibraryError(dlerror());
     74| 
     75| #ifdef _GNU_SOURCE
     76|     }
     77| #endif
     78| }
     79| 
     80| 
     81| void DynamicLibraryHandle::close() throw(DynamicLibraryCloseError)
     82| {
     83| #ifdef _GNU_SOURCE
     84|     if (!_pseudoHandle) {
     85| #endif
     86| 
     87|         if (_opaqueHandle) {
     88|             if (dlclose(_opaqueHandle) != 0)
     89|                 throw DynamicLibraryCloseError(dlerror());
     90| 
     91|             _opaqueHandle = NULL;
     92|         }
     93| 
     94| #ifdef _GNU_SOURCE
     95|     }
     96| #endif
     97| }
     98| 
     99| 
    100| void DynamicLibraryHandle::swap(DynamicLibraryHandle& other) throw()
    101| {
    102| #ifdef _GNU_SOURCE
    103|     if (!_pseudoHandle && !other._pseudoHandle) {
    104| #endif
    105| 
    106|         void *tmp = _opaqueHandle;
    107|         _opaqueHandle = other._opaqueHandle;
    108|         other._opaqueHandle = tmp;
    109| 
    110| #ifdef _GNU_SOURCE
    111|     }
    112| #endif
    113| }
    Comme je le disais, pour ce que je veux faire, ce wrapper ne me convient pas vraiment.
    J'ai donc écrit une classe pour stocker les descripteurs de bibliothèque.
    Si je ferme les bibliothèques externes en commençant par la dernière ouverte, c'est pour rester cohérent avec le compilateur qui détruit les objets alloués statiquement dans l'ordre inverse de leur création.
    Quant au nom, je n'emploie pas le terme « liste » dans le sens du concept de programmation, mais plutôt du concept d'un point de vue général (qui correspondrait à « collection »).
    handle_list.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     1| #ifndef HANDLE_LIST_HPP
     2| #define HANDLE_LIST_HPP
     3| 
     4| 
     5| #include <vector>
     6| 
     7| 
     8| 
     9| class HandleList : private std::vector<void *>
    10| {
    11| 
    12| 
    13| //******************************* NESTED TYPES *******************************//
    14| 
    15|     private:
    16|         typedef std::vector<void *>     _base;
    17|         typedef _base::reverse_iterator iterator;
    18| 
    19|     public:
    20|         typedef _base::value_type       HandleType;
    21| 
    22| 
    23| 
    24| //******************************* CONSTRUCTORS *******************************//
    25| 
    26|     public:
    27|         HandleList() : _base()
    28|         {}
    29| 
    30|     private:
    31|         HandleList(const HandleList&);
    32| 
    33| 
    34| //******************************** DESTRUCTOR ********************************//
    35| 
    36|     public:
    37|         ~HandleList() throw();
    38| 
    39| 
    40| //********************************* OPERATORS ********************************//
    41| 
    42|     private:
    43|         HandleList& operator = (const HandleList&);
    44| 
    45| 
    46| //************************** OTHER MEMBER FUNCTIONS **************************//
    47| 
    48|     public:
    49|         inline
    50|         void insert(const HandleType& handle);
    51| 
    52|         void clear() throw();
    53| 
    54|         using _base::empty;
    55| 
    56|         using _base::size;
    57| 
    58|     private:
    59|         inline
    60|         iterator begin();
    61| 
    62|         inline
    63|         iterator end();
    64| 
    65| 
    66| }; // class HandleList
    67| 
    68| 
    69| 
    70| 
    71| 
    72| //************************** OTHER MEMBER FUNCTIONS **************************//
    73| 
    74| 
    75| inline
    76| void HandleList::insert(const HandleType& handle)
    77| {
    78|     if (handle)
    79|         return _base::push_back(handle);
    80| }
    81| 
    82| 
    83| inline
    84| HandleList::iterator HandleList::begin()
    85| {
    86|     return _base::rbegin();
    87| }
    88| 
    89| 
    90| inline
    91| HandleList::iterator HandleList::end()
    92| {
    93|     return _base::rend();
    94| }
    95| 
    96| 
    97| 
    98| #endif // HANDLE_LIST_HPP
    handle_list.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     1| #include "handle_list.hpp"
     2| 
     3| #include <dlfcn.h>
     4| 
     5| 
     6| 
     7| 
     8| //******************************** DESTRUCTOR ********************************//
     9| 
    10| 
    11| HandleList::~HandleList() throw()
    12| {
    13|     clear();
    14| }
    15| 
    16| 
    17| 
    18| //************************** OTHER MEMBER FUNCTIONS **************************//
    19| 
    20| 
    21| void HandleList::clear() throw()
    22| {
    23|     for (iterator it = begin(), end = this->end(); it != end; ++it)
    24|         dlclose(*it);
    25|     return _base::clear();
    26| }
    Et donc mon interrogation est la suivante : utiliser un « singleton »…
    dynamic_library_handle.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
      1| #ifndef DYNAMIC_LIBRARY_HANDLE_HPP
      2| #define DYNAMIC_LIBRARY_HANDLE_HPP
      3| 
      4| 
      5| #include <string>
      6| 
      7| #include "dynamic_library_error.hpp"
      8| #include "handle_list.hpp"
      9| 
     10| 
     11| 
     12| class DynamicLibraryHandle
     13| {
     14| 
     15| 
     16| //******************************* NESTED TYPES *******************************//
     17| 
     18|     public:
     19|         typedef void (*UserFunction)();
     20| 
     21|     private:
     22|         typedef HandleList::HandleType  HandleType;
     23| 
     24| 
     25| 
     26| //************************** STATIC MEMBER VARIABLES *************************//
     27| 
     28|     private:
     29|         static
     30|         HandleList _handles;
     31| 
     32| 
     33| //***************************** MEMBER VARIABLES *****************************//
     34| 
     35|     private:
     36|         HandleType _opaqueHandle;
     37| 
     38| 
     39| 
     40| //************************** STATIC MEMBER FUNCTIONS *************************//
     41| 
     42|     public:
     43|         static inline
     44|         DynamicLibraryHandle& mainHandle() throw();
     45| 
     46|     private:
     47|         static
     48|         HandleType open(const char *filename = NULL) throw(DynamicLibraryError);
     49| 
     50| 
     51| //******************************* CONSTRUCTORS *******************************//
     52| 
     53|     private:
     54|         DynamicLibraryHandle() throw() : _opaqueHandle()
     55|         {}
     56| 
     57|         DynamicLibraryHandle(const DynamicLibraryHandle&);
     58| 
     59| 
     60| //******************************** DESTRUCTOR ********************************//
     61| 
     62|         ~DynamicLibraryHandle() throw();
     63| 
     64| 
     65| //********************************** GETTERS *********************************//
     66| 
     67|     public:
     68|         inline
     69|         bool isOpened() const throw();
     70| 
     71| 
     72| //********************************* OPERATORS ********************************//
     73| 
     74|     private:
     75|         DynamicLibraryHandle& operator = (const DynamicLibraryHandle&);
     76| 
     77| 
     78| //************************** OTHER MEMBER FUNCTIONS **************************//
     79| 
     80|     public:
     81|         void openLibrary(const std::string& filename);
     82| 
     83|         void closeLibraries() throw();
     84| 
     85|         UserFunction searchFunction(const std::string& name)
     86|         throw(DynamicLibraryError);
     87| 
     88| 
     89| }; // class DynamicLibraryHandle
     90| 
     91| 
     92| 
     93| 
     94| 
     95| //************************** STATIC MEMBER FUNCTIONS *************************//
     96| 
     97| 
     98| inline
     99| DynamicLibraryHandle& DynamicLibraryHandle::mainHandle() throw()
    100| {
    101|     static DynamicLibraryHandle handle;
    102|     return handle;
    103| }
    104| 
    105| 
    106| 
    107| //********************************** GETTERS *********************************//
    108| 
    109| 
    110| inline
    111| bool DynamicLibraryHandle::isOpened() const throw()
    112| {
    113|     return ((_opaqueHandle != NULL) || !_handles.empty());
    114| }
    115| 
    116| 
    117| 
    118| #endif // DYNAMIC_LIBRARY_HANDLE_HPP
    dynamic_library_handle.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     1| #include "dynamic_library_handle.hpp"
     2| 
     3| #include <dlfcn.h>
     4| 
     5| 
     6| 
     7| 
     8| //************************** STATIC MEMBER VARIABLES *************************//
     9| 
    10| 
    11| HandleList DynamicLibraryHandle::_handles;
    12| 
    13| 
    14| 
    15| 
    16| //************************** STATIC MEMBER FUNCTIONS *************************//
    17| 
    18| 
    19| DynamicLibraryHandle::HandleType
    20| DynamicLibraryHandle::open(const char *filename) throw(DynamicLibraryError)
    21| {
    22|     HandleType handle = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
    23|     if (!handle)
    24|         throw DynamicLibraryError(dlerror());
    25| 
    26|     return handle;
    27| }
    28| 
    29| 
    30| 
    31| //******************************** DESTRUCTOR ********************************//
    32| 
    33| 
    34| DynamicLibraryHandle::~DynamicLibraryHandle() throw()
    35| {
    36|     if (_opaqueHandle) {
    37|         dlclose(_opaqueHandle);
    38|         _opaqueHandle = NULL;
    39|     }
    40| }
    41| 
    42| 
    43| 
    44| //************************** OTHER MEMBER FUNCTIONS **************************//
    45| 
    46| 
    47| void DynamicLibraryHandle::openLibrary(const std::string& filename)
    48| {
    49|     _handles.insert( open(filename.c_str()) );
    50| }
    51| 
    52| 
    53| void DynamicLibraryHandle::closeLibraries() throw()
    54| {
    55|     if (_opaqueHandle) {
    56|         dlclose(_opaqueHandle);
    57|         _opaqueHandle = NULL;
    58|     }
    59| 
    60|     _handles.clear();
    61| }
    62| 
    63| 
    64| DynamicLibraryHandle::UserFunction
    65| DynamicLibraryHandle::searchFunction(const std::string& name) throw(DynamicLibraryError)
    66| {
    67|     if (!_opaqueHandle)
    68|         _opaqueHandle = open();
    69| 
    70|     dlerror();
    71| 
    72|     UserFunction f;
    73|     *reinterpret_cast<void **>( &f ) = dlsym(_opaqueHandle, name.c_str());
    74| 
    75|     char *error = dlerror();
    76|     if (error)
    77|         throw DynamicLibraryError(error);
    78| 
    79|     return f;
    80| }
    … ou des « méthodes de classe » ?
    dynamic_library_handle.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     1| #ifndef DYNAMIC_LIBRARY_HANDLE_HPP
     2| #define DYNAMIC_LIBRARY_HANDLE_HPP
     3| 
     4| 
     5| #include <string>
     6| 
     7| #include "dynamic_library_error.hpp"
     8| #include "handle_list.hpp"
     9| 
    10| 
    11| 
    12| class DynamicLibraryHandle
    13| {
    14| 
    15| 
    16| //******************************* NESTED TYPES *******************************//
    17| 
    18|     public:
    19|         typedef void (*UserFunction)();
    20| 
    21|     private:
    22|         typedef HandleList::HandleType  HandleType;
    23| 
    24| 
    25| 
    26| //************************** STATIC MEMBER VARIABLES *************************//
    27| 
    28|     private:
    29|         static
    30|         HandleList _handles;
    31| 
    32|         static
    33|         HandleType _mainHandle;
    34| 
    35| 
    36| 
    37| //************************** STATIC MEMBER FUNCTIONS *************************//
    38| 
    39|     private:
    40|         static
    41|         HandleType& mainHandle();
    42| 
    43|         static
    44|         HandleType open(const char *filename = NULL);
    45| 
    46|     public:
    47|         static inline
    48|         void openLibrary(const std::string& filename);
    49| 
    50|         static
    51|         void closeLibraries() throw();
    52| 
    53|         static
    54|         UserFunction searchFunction(const std::string& name)
    55|         throw(DynamicLibraryError);
    56| 
    57| 
    58| //******************************* CONSTRUCTORS *******************************//
    59| 
    60|     private:
    61|         DynamicLibraryHandle();
    62| 
    63|         DynamicLibraryHandle(const DynamicLibraryHandle&);
    64| 
    65| 
    66| //******************************** DESTRUCTOR ********************************//
    67| 
    68|         ~DynamicLibraryHandle();
    69| 
    70| 
    71| //********************************* OPERATORS ********************************//
    72| 
    73|         DynamicLibraryHandle& operator = (const DynamicLibraryHandle&);
    74| 
    75| 
    76| }; // class DynamicLibraryHandle
    77| 
    78| 
    79| 
    80| 
    81| 
    82| //************************** STATIC MEMBER FUNCTIONS *************************//
    83| 
    84| 
    85| inline
    86| void DynamicLibraryHandle::openLibrary(const std::string& filename)
    87| {
    88|     open(filename.c_str());
    89| }
    90| 
    91| 
    92| 
    93| #endif // DYNAMIC_LIBRARY_HANDLE_HPP
    dynamic_library_handle.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     1| #include "dynamic_library_handle.hpp"
     2| 
     3| #include <dlfcn.h>
     4| 
     5| 
     6| 
     7| 
     8| //************************** STATIC MEMBER VARIABLES *************************//
     9| 
    10| 
    11| 
    12| HandleList DynamicLibraryHandle::_handles;
    13| 
    14| 
    15| DynamicLibraryHandle::HandleType
    16| DynamicLibraryHandle::_mainHandle = NULL;
    17| 
    18| 
    19| 
    20| 
    21| //************************** STATIC MEMBER FUNCTIONS *************************//
    22| 
    23| 
    24| DynamicLibraryHandle::HandleType&
    25| DynamicLibraryHandle::mainHandle()
    26| {
    27|     if (!_mainHandle)
    28|         _mainHandle = open();
    29|     return _mainHandle;
    30| }
    31| 
    32| 
    33| DynamicLibraryHandle::HandleType
    34| DynamicLibraryHandle::open(const char *filename)
    35| {
    36|     HandleType handle = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
    37|     if (!handle)
    38|         throw DynamicLibraryError(dlerror());
    39| 
    40|     _handles.insert(handle);
    41|     return handle;
    42| }
    43| 
    44| 
    45| void DynamicLibraryHandle::closeLibraries() throw()
    46| {
    47|     _mainHandle = NULL;
    48|     return _handles.clear();
    49| }
    50| 
    51| 
    52| DynamicLibraryHandle::UserFunction
    53| DynamicLibraryHandle::searchFunction(const std::string& name) throw(DynamicLibraryError)
    54| {
    55|     dlerror();
    56| 
    57|     UserFunction f;
    58|     *reinterpret_cast<void **>( &f ) = dlsym(mainHandle(), name.c_str());
    59| 
    60|     char *error = dlerror();
    61|     if (error)
    62|         throw DynamicLibraryError(error);
    63| 
    64|     return f;
    65| }

    Autre chose : j'aimerais ne pas exposer la classe « HandleList », puisqu'étant un détail d'implémentation.
    Pour cela, vous la déclareriez en tant que classe interne privée, ou dans un espace de nom anonyme ?
    Ou autrement ?

    Encore une fois, je vous remercie d'avance de vos critiques constructives.

  3. #3
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Décidément, ça ne vous inspire pas beaucoup…
    C'est mon problème qui est trop trivial ? trop complexe ? trop compliqué ?
    J'ai posté trop de code en une seule fois ?
    Ou alors c'est ma tête qui ne vous revient pas ?

    Sinon, c'est mal vu de faire un « UP » sur ce forum, ou pas ?

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Sinon, c'est mal vu de faire un « UP » sur ce forum, ou pas ?
    Oui c'est très mal vu. D'ailleurs à mon avis, tu vas être bientôt puni sur la place publique.

    Bon sinon, concernant tes questions, je vais te dire pourquoi moi je n'y répondrai pas (je ne sais pas ce qu'en pensent les autres). C'est que ces question de conception sont trop vagues pour y répondre comme ça au pied levé. Un programme est conçu au sein d'un contexte particulier, et hors de ce contexte, il est impossible de dire quels sont les bons choix. Et puis même si on connaissait parfaitement le contexte, bien souvent ce sont des choix personnels. Par exemple, singleton ou pas singleton, c'est une fausse question. Un singleton c'est juste une variable globale déguisée. Certains aiment les singletons, certains les détestent (moi au plus ça va, au plus je fous carrément des variables et des fonctions libres globales - dans un namespace intelligemment choisi en revanche).

    My 2 cents.

Discussions similaires

  1. Bibliothèques dynamiques et multithreading!
    Par vonemya dans le forum Visual C++
    Réponses: 2
    Dernier message: 25/10/2007, 17h55
  2. creation bibliothéque dynamique
    Par scorpion06 dans le forum C++
    Réponses: 4
    Dernier message: 19/04/2007, 14h09
  3. Question sur les bibliothques dynamiques
    Par inh40 dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 11/04/2007, 15h16
  4. Chargement bibliothèques dynamiques
    Par Snark dans le forum C++
    Réponses: 3
    Dernier message: 15/12/2006, 15h49
  5. Problème avec la "Gestion des bibliothèques dynamiques"
    Par GoustiFruit dans le forum Delphi
    Réponses: 15
    Dernier message: 31/05/2006, 09h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo