2010-06-18 7 views
1

j'ai une classe basé sur un modèle avec une valeur statique, comme celui-ci:modèle classes statiques à travers les bibliothèques liées dynamiques

template <class TYPE> 
class A{ 
    static TYPE value; 
}; 

dans le code d'une dll j'attribue la valeur statique:

code of DLL_1 

A<float>::value = 2.0; 

I auraient souhaité la valeur à partager par tous les dll que je utilise, par exemple, je veux que:

code of DLL_2 

printf("value on DLL_2 %f",A<float>::value); 

impression sur « 2.0 »

des indices? thx

+0

Variables globales revisitées – ereOn

Répondre

0

Je suppose que vous parlez de Windows spécifiquement, vous mentionnez "DLL". Tant que vous marquez votre classe/structure de modèle comme exportée, vous devriez être en mesure de définir les valeurs dans la DLL et de les utiliser dans une autre DLL ou un autre programme. Pour autant que je comprenne, sur Windows cela nécessite d'utiliser __declspec(dllexport) lors de la compilation de la DLL qui définit les valeurs, et __declspec(dllimport) lors de la compilation de DLL ou de programmes qui utilisent la DLL. Par exemple:
dll.h:

#ifdef BUILDING_MY_DLL 
# define MY_API __declspec(dllexport) 
#else 
# define MY_API __declspec(dllimport) 
#endif 
template<class TYPE> 
struct MY_API A { 
    static TYPE value; 
}; 

dll.cpp.

#include "dll.h" 
template<> 
A<float>::value = 2.0f; 

(Le GCC En cas d'utilisation sur les systèmes ELF (Linux et comme partie __declspec est spécifique de Windows), vous d utilisez __attribute__((__visibility__("default"))) pour exporter la classe/struct, et rien pour l'importer http://gcc.gnu.org/wiki/Visibility

+0

Cela ne fonctionnera pas. La spécialisation n'est pas déclarée dans un fichier d'en-tête, de sorte que l'autre unité de traduction ne saura pas qu'elle existe. En d'autres termes, une règle de définition est violée. –

+0

Cela devrait fonctionner comme les symboles seront émis dans la DLL, puis lorsque la recherche de symbole normale référencée devrait s'appliquer. Je ne parle ici que des variables de classe statiques. (J'ai testé avec g ++ sur Ubuntu, les symboles sont exportés dans la bibliothèque et d'autres bibliothèques ou programmes peuvent les référencer) –

0

Vous pouvez gérer manuellement les instances de vos objets statiques et trouver et résoudre les doublons de cette façon:

MYFILE.H:

// Base class which will make linked list of all static instances 
class Base { 
protected: 
    // make linked list overall template instances 
    static Base *first, *last; 
    Base *prev, *next; 

    Base(); 
    virtual void set_alias(Base *alias) = 0; 
    virtual ~Base(); 
    static void initialize(); 
} 

// Your template class with template static members 
template<typename T> 
class MyClass: public Base { 
protected: 
    T own_data; 
    T *aliased_data; 

    virtual void set_alias(Base *alias) { 
     aliased_data = alias == NULL ? &own_data : ((MyClass<T>*)alias)->aliased_data; 
     //if (aliased_data != &own_data) { 
     // .... here you can merge data from two clones of template, if need 
     //} 
    } 

public: 
    // data accessors 
    inline T& data() { return *aliased_data; } 
    inline const T& data() const { return *aliased_data; } 

    // single instance of class by this you can access staic data field 
    static MyClass instance; 
} 

MonFichier.cpp:

#include <typeinfo> 
#include <string> 

Base *Base::first = NULL; 
Base *Base::last = NULL; 

// connect each created instance to static fields 
Base::Base(): prev(last), next(NULL) { 
    last = (first == NULL ? first : last->next) = this; 
} 

Base::~Base() { 
    (prev == NULL ? first : prev->next) = next; 
    (next == NULL ? last : next->prev) = prev; 
} 

// find all duplicates and connect it togather 
// compare instances by mangled typename 
// Note: Base should contain virtual methods so typeid will works proper 
Base::initialize() { 
    for(Base *i = first; i != NULL; i = i->next) 
     for(Base *j = i->next; j != NULL; j = j->next) 
       if (std::string(typeid(*i).name()) == typeid(*j).name()) 
        j->set_alias(*i); 
} 

Comment utiliser:

... 
// call initialize when program started and DLL 
// with implementation of class Base was loaded 
Base::initialize(); 
... 

... 
// call initialize again when any other dll which uses MyClass loaded 
Base::initialize(); 
... 

... 
// now we can use MyClass from any function (from DLL and/or from main program) 
MyClass<float>::instance.data() = 10.f; 
... 

... 
std::cout << MyClass<float>::instance.data() << std::endl; 
... 

Note: En tout cas vous devez faire dllexport et toutes les autres actions à exporter et importer pour les fonctions:

Base::Base(); 
virtual void Base::set_alias(Base *alias) = 0; 
virtual Base::~Base(); 
static void Base::initialize(); 
Questions connexes