61 votes

Comment puis-je utiliser les classes de la bibliothèque standard (STL) dans mon interface dll ou mon ABI ?

Il y a déjà eu quelques questions sur l'exportation d'une classe qui contient des classes stl en relation avec l'avertissement C4251 de Visual Studio : par exemple cette question ou cette question. J'ai déjà lu l'excellente explication chez UnknownRoad.

Désactiver aveuglément l'avertissement semble un peu dangereux, bien que cela puisse être une option. Envelopper toutes ces classes std et les exporter n'est pas non plus vraiment une option. Après tout, cela s'appelle le Standard Bibliothèque de modèles... C'est-à-dire qu'on veut fournir une interface avec ces classes standard.

Comment puis-je utiliser les stl-classes dans mon interface de dll ? Quelles sont les pratiques courantes ?

89voto

John Dibling Points 56814

Gardez à l'esprit une chose avant de poursuivre votre lecture : Ma réponse vient du point de vue de l'écriture de code portable qui peut être utilisé dans des applications composées de modules compilés sous différents compilateurs. Il peut s'agir de différentes versions ou même de différents niveaux de patchs d'un même compilateur.

Comment puis-je utiliser les classes de stl dans mon programme de gestion de la qualité ? dll-interface ?

Réponse : Vous ne pouvez souvent pas 1 .

Raison : La STL est une bibliothèque de code, pas une bibliothèque binaire comme une DLL. Elle ne dispose pas d'une ABI unique dont l'uniformité est garantie, quel que soit l'endroit où vous l'utilisez. En effet, STL est l'acronyme de " Standard Bibliothèque de modèles", mais le mot clé ici, outre Standard, est Modèle .

La norme définit les méthodes et les membres de données que chaque classe STL doit fournir, et elle définit ce que ces méthodes doivent faire, mais pas plus. En particulier, la norme ne précise pas comment les auteurs de compilateurs doivent implémenter la fonctionnalité définie par la norme. Les auteurs de compilateurs sont libres de fournir une implémentation d'une classe STL qui ajoute des fonctions et des variables membres. no énumérés dans la norme, pour autant que ces membres qui sont définis dans la norme sont toujours là et font ce que la norme dit.

Peut-être qu'un exemple s'impose. Le site basic_string Une classe est définie dans la norme comme ayant certaines fonctions et variables membres. La définition proprement dite fait presque 4 pages dans la norme, mais en voici un extrait :

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
  public:
    // 21.3.3 capacity:
    size_type size() const;
    size_type length() const;
    size_type max_size() const;
    void resize(size_type n, charT c);
    void resize(size_type n);
    size_type capacity() const;
    void reserve(size_type res_arg = 0);
    void clear();
    bool empty() const;
[snip]
};

Considérez le size() y length() fonctions membres. Rien dans la norme ne spécifie que les variables membres doivent contenir ces informations. En fait, aucune variable membre n'est définie, pas même pour contenir la chaîne de caractères elle-même. Alors comment cela est-il mis en œuvre ?

La réponse est : de nombreuses façons différentes. Certains compilateurs peuvent utiliser un size_t pour contenir la taille et une variable char* pour tenir la corde. Une autre pourrait utiliser un pointeur vers un autre magasin de données qui contient ces données (ce qui pourrait être le cas dans une implémentation avec comptage de références). En fait, des versions différentes ou même niveaux de patchs du même compilateur peuvent changer ces détails d'implémentation. Vous ne pouvez pas vous y fier. Ainsi, l'implémentation de MSVC 10 pourrait ressembler à ceci :

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
char* m_pTheString;
};

size_t basic_string::size() const { return strlen(m_pTheString;) }

...Alors que MSVC 10 avec SP1 pourrait ressembler à ceci :

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
[snip]
vector<char> m_TheString;
};

size_t basic_string::size() const { return m_TheString.size(); }

Je ne dis pas qu'ils faire ressemble à ça, je dis qu'ils pourraient. Le fait est que l'implémentation réelle dépend de la plate-forme et que vous n'avez aucun moyen de savoir ce qu'elle sera ailleurs.

Maintenant, disons que vous utilisez MSVC10 pour écrire une DLL qui exporte cette classe :

class MyGizmo
{
public:
  std::string name_;
};

Quel est le sizeof(MyGizmo) ?

En supposant les implémentations que je propose ci-dessus, sous MSVC10, ce sera sizeof(char*) mais sous SP1, ce sera sizeof(vector<char>) . Si vous écrivez une application en VC10 SP1 qui utilise la DLL, la taille de l'objet sera différente de ce qu'elle est en réalité. L'interface binaire a été modifiée.


Pour un autre traitement de cette question, veuillez consulter Normes de codage C++ (Amazon enlace ) numéro 63.


1 : " Vous ne pouvez souvent pas " En fait, vous pouvez exporter des composants de la bibliothèque standard ou tout autre composant de bibliothèque de code (comme Boost) avec une certaine fiabilité lorsque vous avez un contrôle total sur les chaînes d'outils et les bibliothèques.

Le problème fondamental est qu'avec les bibliothèques de code source, les tailles et les définitions des éléments peuvent être différentes entre les différents compilateurs et les différentes versions de la bibliothèque. Si vous travaillez dans un environnement où vous contrôlez ces deux éléments partout où votre code est utilisé, alors vous n'aurez probablement pas de problème. Par exemple, dans une société commerciale où tous les systèmes sont écrits en interne et utilisés uniquement en interne, il est possible de le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X