我的代码是针对多个.dll文件构建的,我有一个具有静态成员变量的模板类。
我希望这个静态成员变量的相同实例在所有dll中都可用,但它不起作用:我在每个中看到不同的实例(不同的值)。
当我不使用模板时,没有问题:初始化其中一个源文件中的静态成员,并在类上使用__declspec(dllexport)和__declspec(dllimport)指令。但它不适用于模板。有没有办法让它发挥作用?
我看到一些使用“extern”的建议解决方案,但我认为我不能使用它,因为我的代码应该与visual studio 2002和2005一起使用。
谢谢。
澄清:我希望每种不同类型的模板实例都有一个不同的静态变量实例。但是如果我在2个不同的dll中实例化相同类型的模板,我希望在它们中都有相同的变量。
答案 0 :(得分:4)
还有以下解决方案:
详细说明如何做到这一点:
答案 1 :(得分:3)
问题是每个不同的模板实例化都是一个不同的类型,它有自己的静态变量,不与具有不同模板参数的其他实例共享。您可以提供包含静态变量的非模板基类。
答案 2 :(得分:2)
创建模板专门化,然后导出专业化的静态成员。
答案 3 :(得分:2)
似乎有一种方法可以做到这一点,对使用模板类的代码的限制较少。
使静态成员成为指针。创建一个已修复已知类型并可从DLL导出的全局映射。映射使用类的typeid()作为键,并使用“每个类的全局变量”的地址作为值。通过一个函数初始化静态成员,该函数测试该类是否已存在于映射中,如果是,则强制该类的第二个版本(在第二个DLL中)指向该类的第一个版本的静态变量。
这样每个DLL都有一个独特的静态对象,但每个DLL也有一个指针,所有指针都指向同一个静态对象。
这是一些伪代码,假设静态类型与模板参数相同(但应该很容易适应其他情况)。
map<string,void*> dllexport the_map; // instantiate this once in a single DLL
T *set_the_global(T *candidate) {
map<string,void*>::iterator r = the_map.find(string(typeid(the_class<T>).name()));
if(r == the_map.end()) {
the_map[string(typeid(the_class<T>).name())] = (void*)candidate;
return candidate; // new class: use it as global storage location
} else {
return (T*)(r->second); // class already has global storage location
}
}
template <class T> class the_class {
virtual void something(); // so RTTI exists
static T *the_global; // use this! always points to the same object
static T one_per_dll; // only used in initialisation
};
template<class T> the_class<T>::one_per_dll;
template<class T> the_class<T>::the_global = set_the_global(&the_class<T>::one_per_dll)
答案 4 :(得分:1)
我可以看到这个问题有两个修复。
首先,您使用另一个类(非模板)来保存此静态值 - 或者使其成为全局值? - 并从dll中导出。
另一个稍微复杂一点,因为您在代码中实例化模板并导出实例化的模板化值。举一个例子说我有一种特殊的链表模板化类,需要在DLL中共享一个静态值。我编写的代码是模板化的,但它只用于少数几种类型。我会实例化这样的类:
template <class T> class Foo;
template<> class Foo<int> {};
然后你可以导出。
中包含的静态变量__declspec(dllexport) int Foo<int>::StaticMember = 0;
(或类似的东西,我做dll导出/导入时有点生疏。)
虽然真正的问题是你为什么要这样做,但从技术上讲,DLL可以跨进程使用,只有一个副本存储在内存中。您是否真的希望所有流程只有一个静态版本,或者每个流程一个版本?
答案 5 :(得分:1)
您已尝试过这种用法:
#pragma data_seg(".JOE")
HWND hWndServer = NULL;
HHOOK hook = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.JOE,rws")
注意变量需要波束初始化。
更多信息: http://msdn.microsoft.com/en-us/library/ms997537.aspx http://www.flounder.com/hooks.htm
祝你好运。答案 6 :(得分:0)