模板、静态和 dll

Template, statics and dll

本文关键字:dll 静态 模板      更新时间:2023-10-16

>我正在尝试导出定义中带有静态变量的函数模板。

.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/主.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(并在创建的.lib文件中准确搜索(符号到符号(此字符串 - 在构建 DLL 之后。 如果存在 - 一切正常,否则没有意义继续(使用 exe(

在 exe 中:

#include "../foo_dll/foo.h"
Foo::Get<int>() = 3;
Foo::Set();
if (Foo::Get<int>() != 10)
{
__debugbreak();
}