跨动态链接库的模板静态类

时间:2010-06-18 11:40:18

标签: c++ class templates static

我有一个带有静态值的模板化类,如下所示:

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

在dll的代码中我分配静态值:

code of  DLL_1

A<float>::value = 2.0;

我希望我正在使用的所有dll共享该值,即我想要:

code of DLL_2

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

打印出“2.0”

任何线索? THX

2 个答案:

答案 0 :(得分:0)

我假设你正在谈论Windows,你提到“DLL”。只要将模板类/结构标记为已导出,您就应该能够在DLL中设置值并在另一个DLL或程序中使用它们。 据我所知,在Windows上,这需要在编译设置值的DLL时使用__declspec(dllexport),在编译使用DLL的DLL或程序时使用__declspec(dllimport)。例如:
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;

__declspec部分是特定于Windows的。在ELF系统(Linux等)上使用GCC时,您将使用__attribute__((__visibility__("default")))导出类/结构,而无需导入它。http://gcc.gnu.org/wiki/Visibility有一些模板代码,您可以更轻松地设置它。

答案 1 :(得分:0)

您可以通过以下方式手动管理静态对象的实例并查找和解决重复项:

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;
}

MYFILE.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);
}

使用方法:

...
// 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;
...

注意:无论如何,您需要为函数导出和导入dllexport和任何其他操作:

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