Implications de l’utilisation de std :: vector dans une fonction exscope par une DLL

J’ai deux classes exscopes par la DLL, A et B. La déclaration de A contient une fonction qui utilise std :: vector dans sa signature, comme

class EXPORT A{ // ... std::vector myFunction(std::vector const &input); }; 

(EXPORT est la macro habituelle pour mettre en place _ declspec (dllexport) / _declspec (dllimport) en conséquence.)

En lisant les problèmes liés à l’utilisation des classes STL dans une interface DLL, je résume en résumé:

  • L’utilisation de std :: vector dans une interface DLL nécessiterait que tous les clients de cette DLL soient compilés avec la même version du même compilateur, car les conteneurs STL ne sont pas compatibles binarys. Pire encore, en fonction de l’utilisation de cette DLL par les clients conjointement avec d’autres DLL, l’API DLL «instable» peut endommager ces applications clientes lorsque des mises à jour du système sont installées (par exemple, des packages Microsoft KB) (vraiment?).

  • Malgré ce qui précède, si nécessaire, std :: vector peut être utilisé dans une API DLL en exportant std::vector comme suit:

     template class EXPORT std::allocator; template class EXPORT std::vector; 

    cependant, cela est généralement mentionné dans le contexte lorsque l’on souhaite utiliser std :: vector en tant que membre de A (http://support.microsoft.com/kb/168958).

  • L’article de support Microsoft suivant explique comment accéder aux objects std :: vector créés dans une DLL via un pointeur ou une référence à partir de l’exécutable (http://support.microsoft.com/default.aspx?scid=kb;EN-US; Q172396). La solution ci-dessus consistant à utiliser la template class EXPORT ... semble également applicable. Cependant, l’inconvénient résumé au premier point semble restr.

  • Pour éliminer complètement le problème, il faudrait envelopper std :: vector et changer la signature de myFunction , PIMPL, etc.

Mes questions sont:

  • Le résumé ci-dessus est-il correct ou manque-t-il ici quelque chose d’essentiel?

  • Pourquoi la compilation de ma classe ‘A’ ne génère-t-elle pas l’avertissement C4251 (la classe ‘std :: vector ‘ doit avoir une interface dll pour pouvoir être utilisée par les clients de …)? Je n’ai aucun avertissement du compilateur désactivé et je ne reçois aucun avertissement sur l’utilisation de std :: vector dans myFunction dans la classe exscope A (avec VS2005).

  • Que faut-il faire pour exporter correctement myFunction dans A? Est-il viable d’exporter simplement std::vector et l’allocateur de B?

  • Quelles sont les implications du retour de std :: vector par valeur? En supposant qu’un exécutable client a été compilé avec un compilateur différent (-version). Le problème persiste-t-il lors du renvoi par valeur où le vecteur est copié? Je suppose oui. De même pour passer std :: vector comme référence constante: l’access à std::vector (qui pourrait être construit par un exécutable compilé avec un compilateur différent (-version)) myFunction entraîner des problèmes dans myFunction ? Je suppose que oui encore ..

  • Le dernier point mentionné ci-dessus est-il vraiment la seule solution propre?

Merci d’avance pour vos commentaires.

Malheureusement, votre liste est vraiment très précise. La cause première de ceci est que DLL à DLL ou DLL à EXE est définie au niveau du système d’exploitation, tandis que l’interface entre les fonctions est définie au niveau d’un compilateur. D’une certaine manière, votre tâche est similaire (bien qu’un peu plus facile) à celle de l’interaction client-serveur, lorsque le client et le serveur manquent de compatibilité binary.

Le compilateur mappe ce qu’il peut sur la manière dont l’importation et l’exportation de DLL sont effectuées dans un système d’exploitation particulier. Etant donné que les spécifications de langage donnent beaucoup de liberté aux compilateurs en ce qui concerne la disposition binary des types définis par l’utilisateur et parfois même des types intégrés (rappelez-vous que la taille exacte de int dépend du compilateur, tant que les exigences de dimensionnement minimales sont satisfaites), l’importation et l’exportation à partir de DLL doivent être effectuées manuellement pour assurer la compatibilité au niveau binary.

Lorsque vous utilisez la même version du même compilateur, ce dernier problème ci-dessus ne crée pas de problème. Cependant, dès qu’un compilateur différent entre dans l’image, tous les paris sont ouverts: vous devez revenir aux interfaces clairement typées et introduire des wrappers pour conserver des interfaces attrayantes dans votre code.

J’ai eu le même problème et j’ai trouvé une solution intéressante.
Au lieu de passer std:vector , vous pouvez passer un QVector depuis la bibliothèque Qt .
Les problèmes que vous citez sont ensuite traités à l’intérieur de la bibliothèque Qt et vous n’avez pas du tout besoin de vous en occuper.
Bien sûr, le coût consiste à utiliser la bibliothèque et à accepter ses performances légèrement inférieures.
En termes de temps de codage et de débogage économisé, cette solution en vaut la peine.