jac*_*cob 5 c++ templates mingw dllimport dllexport
当涉及类模板时,我在使用 MinGW-w64(基于 MSYS2 的 GCC 11.3.0)将一个简单的 Windows 可执行文件正确链接到一个简单的 DLL 时遇到问题。最小的再现器如下。
库的完整代码(library.cpp)是
template <class T> class __attribute__((dllexport)) TestClass
{
public:
void member() { __builtin_printf("member from library\n"); }
void other_member();
};
template class __attribute__((dllexport)) TestClass<int>;
template <class T> void __attribute__((dllexport)) TestClass<T>::other_member () {}
Run Code Online (Sandbox Code Playgroud)
我用它来编译它
g++ -std=c++11 library.cpp -o library.dll -shared -Wl,--out-implib,library.dll.a -Wl,--output-def,library.def
Run Code Online (Sandbox Code Playgroud)
程序的完整代码(program.cpp)是
template <class T> class __attribute__((dllimport)) TestClass
{
public:
void member() { __builtin_printf("member from program\n"); }
void other_member();
};
extern template class __attribute__((dllimport)) TestClass<int>;
int main (void)
{
TestClass<int> test;
test.member();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用它来编译它
g++ -std=c++11 program.cpp library.dll.a -o program.exe
Run Code Online (Sandbox Code Playgroud)
程序与 DLL 的链接失败,并显示undefined reference to TestClass<int>::member(). 事实证明,链接失败可以通过两种方式解决:
TestClass<T>::other_member中注释掉。然后程序正确链接到库中的 并打印“成员来自库”。TestClass<int>::member我理解第一点,即避免使用外部模板并进行本地隐式实例化。当我通过优化编译代码时也会发生这种情况。
但第二点让我困惑。为什么 的体外定义会TestClass<T>::other_member破坏 的导出TestClass<T>::member?
免责声明:我正在调试别人的程序,因此设计选择不是我的。
据我所知:
没有library.cpp类模板的(显式)实例化,也没有所述类的成员函数。
template class __attribute__((dllexport)) TestClass<int>;
Run Code Online (Sandbox Code Playgroud)
将是一个(显式的)“模板专业化前向声明”......(因为它当然会)。
长话短说,如果(这是一个大胆的假设)我是对的,你只需要{}在后面添加即可TestClass<int>“定义”类型。
回答:
为什么 TestClass::other_member 的体外定义会破坏 TestClass::member 的导出?
我更加没有信心了。但是为什么要定义 的特化成员函数呢TestClass?template到底需要吗?
cf:显式(完整)模板专业化