跨DLL的c++成员函数显式模板实例化
C++ member function explicit template instantiation across DLL
我在Windows 8.1 Update 1
上使用Visual Studio 2013
在C++
中创建DLL
。有一个名为XMLData
的类,它有一个名为getAttribute
的公共成员函数。
XMLData.h
namespace DDGL
{
class DLL_EXPORTED XMLData
{
...
// const char* is used to avoid problems with trying to pass an
// std::string over DLL boundaries
template <typename Type> Type getAttribute (const char* attribute) const;
...
};
}
在DLL内部,每次使用都像您期望的那样实例化并且工作良好。
然而,在一个应用程序中,我当然会得到未定义的引用,<typename Type>
在DLL中没有使用。
因此,我尝试使用显式模板实例化(我宁愿不把实现放在header中,如果有的话,作为学习练习):
XMLData.cpp
namespace DDGL
{
...
// getAttribute definition
...
template float XMLData::getAttribute(const char* attribute) const;
...
}
然而,我仍然在使用DLL的应用程序中得到一个未解决的外部:
error LNK2019: unresolved external symbol "public: float __thiscall DDGL::XMLData::getAttribute<float>(char const *)const " (??$getAttribute@M@XMLData@DDGL@@QBEMPBD@Z) referenced in function "class std::shared_ptr<class DDGL::IGameObject> __cdecl SimpleExplodingRocketDeserialiser(class DDGL::XMLData)" (?SimpleExplodingRocketDeserialiser@@YA?AV?$shared_ptr@VIGameObject@DDGL@@@std@@VXMLData@DDGL@@@Z)
DLL_EXPORTED
#ifdef DDGL_DLL_BUILDING
#define DLL_EXPORTED __declspec(dllexport)
#else
#define DLL_EXPORTED __declspec(dllimport)
#endif
我哪里错了?
虽然@OMGtechy解决方案有效,但我认为这是多余的。为模板声明和模板定义指定DLL_EXPORTED
就足够了。
头文件:
namespace DDGL
{
class DLL_EXPORTED XMLData
{
template <typename Type> DLL_EXPORTED Type getAttribute (const char* attribute) const;
};
}
在.cpp文件中定义函数:
namespace DDGL
{
template<> DLL_EXPORTED float XMLData::getAttribute(const char* attribute) const {
// Function body goes here
}
}
在msvc++ 2017上测试。
一些想法:我认为这将是合乎逻辑的,如果DLL_EXPORTED
类定义工作在其模板方法。非模板化方法不需要在每个方法上再次设置DLL_EXPORTED
。模板方法有什么不同?我不确定。
问题是,虽然我确实正确地显式实例化了模板,但我并没有为每个实例化导出符号。
解决方法如下:
namespace DDGL
{
class DLL_EXPORTED XMLData
{
...
// const char* is used to avoid problems with trying to pass an
// std::string over DLL boundaries
template <typename Type> Type getAttribute (const char* attribute) const;
...
};
DLL_TEMPLATE_CLASS_MEMBER float XMLData::getAttribute(const char* attribute) const;
}
其中DLL_TEMPLATE_CLASS_MEMBER
定义为:
#ifdef DDGL_DLL_BUILDING
#define DLL_TEMPLATE_CLASS_MEMBER template DLL_EXPORTED
#else
#define DLL_TEMPLATE_CLASS_MEMBER extern template DLL_EXPORTED
#endif
正确地导出了用于显式模板实例化的符号,并允许我在DLL外使用它们。
相关文章:
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 模板化类构造函数的模板实例化
- 何时需要实例化函数模板定义?
- clang:使用 O3 导出隐式实例化函数的符号
- 如何调用模板函数的每个实例化函数
- 使用泛型类型显式实例化函数模板
- 使用自动>decltype方法显式实例化函数
- MSVC 编译器实例化函数模板的默认定义,即使存在专用化
- 如何使用模板模板参数显式实例化函数
- 实例化函数模板的编译问题
- Lua到c++,用于实体修改的实例化函数
- 当类型参数为空时,无法实例化函数模板
- 调用实例化函数时发生链接器错误
- 实例化函数的多个模板并在运行时选择的通用解决方案
- 使用不完整类型显式实例化函数模板
- 实例化函数模板时出错
- 禁止使用迭代器形参实例化函数模板