我正在尝试导出定义中带有静态变量的功能模板。
.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)
}
最佳答案
您需要每个带有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
),并在生成dll后在创建的.lib文件中精确搜索(符号到符号)。如果存在-一切正常,否则毫无意义(使用exe)并在exe中:
#include "../foo_dll/foo.h"
Foo::Get<int>() = 3;
Foo::Set();
if (Foo::Get<int>() != 10)
{
__debugbreak();
}
关于c++ - 模板,静态和dll,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52242984/