2010-09-23 3 views
1

J'ai une bibliothèque partagée lib.so contenant une classe Foo. Je charge dynamiquement (avec dlopen sous UNIX) lib.so. Après le chargement, je veux créer une instance de Foo.
Puis-je utiliser simplement new opérateur pour créer un objet de Foo, ou je devrais créer une méthode d'usine exportée placé dans lib.so qui va créer cet objet pour moi?Le constructeur d'une classe d'une bibliothèque partagée est-il exporté?

En fait la question serait si le constructeur de Foo est exporté et s'il pourrait simplement être appelé avec l'opérateur new. Je pense que toutes les classes et méthodes dans la bibliothèque partagée sous UNIX sont exportées par défaut, et je n'ai pas besoin de les exporter explicitement comme sous Windows.

En plus de cacher la façon de créer (et éventuellement l'initialisation) objet de Foo, y at-il d'autres raisons d'utiliser la méthode de l'usine lors de la création objet de la classe contenu dans la bibliothèque partagée?

Répondre

0

Il y a des problèmes avec cette approche. En particulier, lors de l'utilisation de différentes versions du même compilateur pour la bibliothèque et le programme, vous n'avez aucune garantie que les fonctions membres de classe ont le même nom de symbole.

Par conséquent, aller à l'approche de l'usine, et opaques types de pointeur C:

// .cpp file 
class Foo { ... }; 

// .h file 
struct FooHandle; 

#ifdef __cplusplus 
extern "C" 
{ 
    FooHandle* constructFoo(...); 
    void releaseFoo(FooHandle*); 
    int someFooMethod(FooHandle*, int param1, ...); 
} 
#endif 

Utilisez toujours les fonctions C et types de pointeurs opaques lors de l'exportation des bibliothèques partagées.

+1

Je crois que GCC maintient une API C++ compatible à la version 3.3.6. Voir http://stackoverflow.com/questions/3718746/g-version-compatibility –

+0

@Zan: cela ne change pas le problème: un utilisateur avec un autre compilateur ne pourrait pas importer les objets partagés compilés avec gcc. –

+2

Vous avez dit "différentes versions du * même * compilateur", c'est pourquoi j'ai fait le commentaire. –

0

La réponse de base est oui. Le diable est dans les détails cependant. Sous Windows, à l'aide du compilateur Microsoft C++, TOUS les symboles, qu'il s'agisse de méthodes, de variables, etc. ne sont pas exportés par défaut pour une DLL. Vous devez exporter explicitement des fonctions, des classes et/ou des variables globales. Je crois que c'est aussi le cas pour le compilateur Borlands (je peux me tromper).

Avec GCC, tout était exporté par défaut et vous ne pouviez pas vraiment le contrôler. Il y a quelques années, cela a changé avec un attribut qui a été ajouté (je ne me rappelle pas exactement comment il s'appelait mais cela fonctionnait d'une manière similaire à l'équivalent de Microsoft __declspec (dllexport)). Par conséquent, si vous définissez une classe et que vous la marquez comme exportée (quelle que soit votre préférence), son constructeur sera exporté. Cependant, comme le mentionne l'affiche précédente, en raison de la nature de C++, le nom du symbole change en fonction du compilateur que vous utilisez, et aussi, parfois, de la version du compilateur C++. Ce n'est pas nécessairement un problème, cela dépend de la façon dont vous voulez utiliser les choses, mais cela signifie que vous devez en être conscient.

+0

options de visibilité et attribut ... – Tomek

Questions connexes