2009-05-29 4 views
4

Au fil des mois, j'ai écrit quelques fonctionnalités assez génériques que je veux construire en tant que bibliothèque et lier dynamiquement plutôt que d'importer 50 fichiers en-tête/source. Le projet est maintenu dans Xcode et Dev-C++ (je comprends que je devrais aller en ligne de commande pour faire ce que je veux) et doit être lié à OpenGL et SDL (dynamiquement dans le cas de SDL). Les plates-formes cibles sont Windows et OS X.Création d'un code source C++ en tant que bibliothèque - par où commencer?

Qu'est-ce que je regarde du tout?

  • Quel sera le point d'entrée de ma bibliothèque si elle en a besoin?
  • Que dois-je changer dans mon code? (conventions d'appel?)
  • Comment le libérer? Je crois comprendre est que les en-têtes et la bibliothèque compilé (.dll, .dylib (, .framework), quoi que ce sera) doivent être disponibles pour le projet - d'autant plus que les fonctionnalités du modèle ne peuvent pas être inclus dans la bibliothèque par nature.
  • De quoi d'autre dois-je être conscient?
+1

Avez-vous envisagé de le construire comme un .lib? Cela signifie que votre application doit avoir accès aux fichiers d'en-tête, mais pas aux fichiers source. Cela signifierait moins de modifications par rapport à la route de la DLL. – Kieveli

Répondre

11

je recommande la construction comme une bibliothèque StatC plutôt que d'une DLL. Beaucoup de problèmes liés à l'exportation de fonctions et de classes C++ disparaissent si vous le faites, à condition que vous ayez uniquement l'intention de créer un lien avec le code produit par le même compilateur avec lequel vous avez construit la bibliothèque.

Construire une bibliothèque statique est très simple car il s'agit juste d'une collection de fichiers .o/.obj - un peu comme un fichier ZIP mais sans compression. Il n'est pas nécessaire d'exporter quoi que ce soit - il suffit d'inclure la bibliothèque dans la liste des fichiers avec lesquels votre application est liée. Pour accéder à des fonctions ou classes spécifiques, il suffit d'inclure le fichier d'en-tête correspondant. Notez que vous ne pouvez pas vous débarrasser des fichiers d'en-tête - le modèle de compilation C++, en particulier pour les templates, en dépend.

2

Il peut être problématique d'exporter une bibliothèque de classes C++ à partir d'une bibliothèque dynamique, mais cela est possible.
Vous devez marquer chaque fonction à exporter à partir de la DLL (la syntaxe dépend du compilateur). Je fouille pour voir si je peux trouver comment le faire à partir de xcode. Dans VC, c'est __declspec (dllexport) et dans CodeWarrior c'est #pragma export on/# pragma export off.

Ceci est parfaitement raisonnable si vous n'utilisez que votre binaire en interne. Cependant, un problème est que les méthodes C++ sont nommées différemment par différents compilateurs. Cela signifie que personne qui utilise un compilateur différent ne pourra utiliser votre DLL, à moins que vous n'exportiez que des fonctions C.

De même, vous devez vous assurer que les conventions d'appel correspondent dans la DLL et le client de la DLL. Cela signifie que vous devez avoir le même attribut de convention d'appel par défaut transmis au compilateur pour la DLL ou le client, ou mieux, définir explicitement la convention d'appel sur chaque fonction exportée dans la DLL, de sorte que cela n'a aucune importance la valeur par défaut est pour le client.

Cet article explique la question du nom: http://en.wikipedia.org/wiki/Name_decoration

+0

il semble que xcode utilise #pragma GCC visibilité push (caché) et #pragma GCC visibilité push (par défaut) pour contrôler la visibilité des symboles, tandis que Dev-C++ utilise la syntaxe VC (?). – zyndor

1

La norme C++ ne définit pas un ABI standard, et c'est une mauvaise nouvelle pour les personnes qui essaient de construire des bibliothèques C++.Cela signifie que vous obtenez un comportement différent de votre code compilé en fonction des drapeaux qui ont été utilisés pour le compiler, et cela peut conduire à des bogues mystérieux dans le code qui compile et relie très bien. Cela va au-delà de conventions d'appel différentes - Le code C++ peut être compilé pour supporter ou non le RTTI, la gestion des exceptions, et avec diverses optimisations qui peuvent affecter la disposition mémoire des instances de classe, sur lesquelles repose le code C++.

Alors, que pouvez-vous faire? Je construirais des bibliothèques C++ dans mon arborescence source, et je m'assurerais qu'elles sont construites dans le cadre de la construction de mon projet, et que toutes les bibliothèques et le code qui les lie utilisent les mêmes drapeaux de compilateur. Notez que le mangling de noms, qui devait au moins vous empêcher de lier des fichiers objet qui ont été compilés avec des compilateurs/indicateurs de compilation différents, ne fonctionne que pour la plupart, et il y a certaines choses que vous pouvez faire, surtout avec GCC. dans le code qui lie juste bien et échoue à l'exécution. Vous devez être très prudent avec les bibliothèques C++ dynamiques fournies par le fournisseur (QT sur la plupart des distributions Linux, par exemple). J'ai vu des exemples de bibliothèques fournies par le fournisseur qui ont été compilées de manière à empêcher certaines choses de fonctionner correctement. Par exemple, certaines versions de RedHat Linux (peut-être toutes) ont désactivé les exceptions dans QT, ce qui a rendu impossible l'interception des exceptions dans main() si les exceptions étaient lancées dans un rappel QT. Amusement.

+0

Bien sûr, il en va de même pour tous les autres langages informatiques - je ne connais pas de langage normalisé standardisant l'ABI. –

+1

Il y a toujours Java, mais ce ne serait qu'une norme de fait, je ne vais pas le mentionner ici. –

+0

Non, java peut être gpod contre-exemple à mon instruction générale. Je ne suis pas sûr qu'il puisse être dit d'avoir un ABI cependant. –

Questions connexes