web-dev-qa-db-fra.com

Utilisation de bibliothèques compilées libstdc ++ avec clang ++ -stdlib = libc ++

Je travaille en C++ sous Mac OS X (10.8.2) et j'ai récemment trouvé le besoin d'utiliser des fonctionnalités C++ 11, qui sont disponibles via le compilateur clang ++ en utilisant libc ++ stdlib. Cependant, j'ai également besoin d'utiliser une bibliothèque héritée compilée et liée à libstdc ++ (provenant de MacPorts).

Ce faisant, j'ai eu des erreurs de liaison, car les en-têtes des bibliothèques héritées utilisant, par exemple, std::string, à résoudre par rapport au std::__1::basic_string (c'est-à-dire l'implémentation libc ++ de std::string) à la place du std::basic_string la mise en oeuvre.

Existe-t-il un moyen de mélanger les deux bibliothèques en développement (par exemple en utilisant des drapeaux de préprocesseurs?)

68
user1690715

Ce que vous voyez, c'est l'utilisation d'espaces de noms en ligne pour obtenir le contrôle de version ABI.

Ce que cela signifie:

Le libstdc ++ std::string est une structure de données différente de la libc ++ std::string. Le premier est un modèle compté par référence, tandis que le second ne l'est pas. Bien qu'ils soient compatibles API, ils ne sont pas compatibles ABI. Cela signifie que si vous construisez un std::string avec libstdc ++, puis le transmettre à un autre code lié à libc ++, le code récepteur penserait qu'il a un libc ++ std::string. C'est à dire. le récepteur n'aurait aucune idée qu'il devrait incrémenter ou décrémenter les comptages de référence.

Sans espaces de noms en ligne, le résultat serait une erreur d'exécution. Le mieux que vous puissiez espérer est un crash. Avec les espaces de noms en ligne, cette erreur d'exécution est traduite en une erreur de temps de liaison.

Pour vous le programmeur, le libstdc ++ std::string et libc ++ std::string ressemble au même type. Mais pour l'éditeur de liens, ils ressemblent à des types complètement différents (l'indice est le std::__1 espace de noms). Et la vue de l'éditeur de liens est correcte. Ils sont des types complètement différents.

Alors oui, vous pouvez manipuler certains drapeaux de préprocesseur pour que les choses soient liées. Mais alors vous auriez un diable de temps à déboguer les bogues d'exécution résultants.

La seule façon de faire ce que vous voulez est de ne pas impliquer les interfaces entre ces dylibs std:: types tels que string. Par exemple, vous pouvez passer des tableaux de char à la place. Vous pouvez même transférer la propriété de la mémoire du code lié libstdc ++ au code lié libc ++ et vice-versa (ils passeront tous les deux dans le même pool malloc).

92
Howard Hinnant