我正在尝试导出定义中带有静态变量的功能模板。
.dll / Foo.h:
#ifdef _DLL
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
class API Foo
{
public:
template<typename T>
static T& Get()
{
static T _instance;
return _instance;
}
static void Set();
}
我希望.dll和.exe进行的调用引用相同的“ _instance”对象。我知道我可以通过在.cpp中定义静态变量来做到这一点。但是在这种情况下,我正在处理模板,因此有点卡住。
编辑: 发生什么事的例子..
.dll / Foo.cpp:
void Foo::Set()
{
Foo::Get<int>() = 10;
}
.exe / main.cpp:
int main()
{
auto & x = Foo::Get<int>();
x = 3;
std::cout << x; // 3
Foo::Set();
std::cout << x; // 3 (I want it to be 10)
}
答案 0 :(得分:0)
每个带有API
(__declspec(dllexport)
或__declspec(dllimport)
)的模板都需要分开标记,并且不能将其内联到类代码中。
Foo.h文件为:
#ifdef _DLL
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
class API Foo
{
public:
template<typename T>
API static T& Get();
static void Set();
};
请注意,尽管所有Get()
类也都用API
进行了标记,但我们仍将Foo
与API
分开(事实上,类标记对模板功能没有影响,因此需要它标记为单独)。并且此处没有实现Get
-导出的函数无论如何都不能内联。
因此dll代码(Foo.cpp)必须如下所示:
#include "foo.h"
template<typename T>
API T& Foo::Get()
{
__pragma(message("__imp_" __FUNCDNAME__)) // for debug
static T _instance;
return _instance;
}
void Foo::Set()
{
Foo::Get<int>() = 10;
}
请注意,我们再次在函数体的实现中显式使用API
(__declspec(dllexport)
)。这一点非常重要-如果您在此处跳过API
,但编译器不会警告您,但如果不这样做,则Get
将不会导出。
确保此时所有正确-复制__pragma(message("__imp_" __FUNCDNAME__))
(看起来像__imp_??$Get@H@Foo@@SAAEAHXZ
)产生的字符串并精确搜索 (符号到符号)此字符串在创建的 .lib 文件中-构建dll之后。如果存在-一切正常,否则无法继续(使用exe)
并在exe中:
#include "../foo_dll/foo.h"
Foo::Get<int>() = 3;
Foo::Set();
if (Foo::Get<int>() != 10)
{
__debugbreak();
}