C++ DLL+;出口类+;模板成员func=未解析的外部符号。有机会修理吗?

C++ DLL+;出口类+;模板成员func=未解析的外部符号。有机会修理吗?,c++,dll,dynamic-linking,member-functions,template-function,C++,Dll,Dynamic Linking,Member Functions,Template Function,首先,这不是一个重复的问题,因为1)这是一个链接器问题,编译器成功通过,因为我已显式实例化。2) 这不是关于模板类,而是关于模板成员函数,3)我对代码结构有一些限制,因此一些现有技巧不适用。我在这里搜索了我的标题,前几个线程(,)都是关于模板类的,而不是模板成员函数。其他一些线程实际上在讨论实例化失败,所以实际上是编译器问题,但我尝试了显式实例化,并且编译已经成功通过,重复。所以我希望你能克制一下诱惑,把我的问题作为重复来结束,我的帖子来了 环境: Windows10版本1803 Visual

首先,这不是一个重复的问题,因为1)这是一个链接器问题,编译器成功通过,因为我已显式实例化。2) 这不是关于模板类,而是关于模板成员函数,3)我对代码结构有一些限制,因此一些现有技巧不适用。我在这里搜索了我的标题,前几个线程(,)都是关于模板类的,而不是模板成员函数。其他一些线程实际上在讨论实例化失败,所以实际上是编译器问题,但我尝试了显式实例化,并且编译已经成功通过,重复。所以我希望你能克制一下诱惑,把我的问题作为重复来结束,我的帖子来了

环境:

  • Windows10版本1803
  • Visual Studio 2015更新3
  • 在VS中调试x64模式
资料来源:

有两个项目:

1) DllProject作为dll构建,包含两个源:dll.h和dll.cpp

Dll.h:

#pragma once

#ifdef _WINDLL
#define API_TYPE __declspec(dllexport)
#else
#define API_TYPE __declspec(dllimport)
#endif

class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
};
我已经在第8行的Dll.cpp中显式地实例化了模板成员函数
Func
,因此编译工作正常。但是链接器无法从
CallFunc
内部链接到dll中的该实例化函数。我认为该函数是在dll中实例化的,而不是在exe中,因为我为该类指定了
\uu declspec(dllimport)
。我不知道为什么
CallFunc
找不到
Func
;就在它的正上方

源代码与大型开放源代码隔离并最小化(DllProject对应库本身,ExeProject测试代码),因此模板成员函数的实现和声明分为两个文件,这在大型项目中是不可避免的,并且代码结构不会改变。DllProject,顾名思义,是作为一个dll构建的,尽管构建和链接所有静态库的工作没有任何问题。我已经做了很多搜索,但是这个论坛和其他论坛中的线程要么将模板实现移动到类声明中,要么通过#include a.tpp文件移动到头中,所有这些都违反了上述限制,或者建议以各种表达方式显式实例化,我想我已经这样做了,因为编译已经通过了

我尝试过以下方法:

1) 在版本配置下编译

2) 使用
inline
(甚至
\uu forceinline

3) 将显式专门化放在类中的Dll.h中:

class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template<> void AClass::Func<float>(float&);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
};
class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
    template void AClass::Func<float>(float&);
};
但它们都不起作用并报告相同的错误

8) 将显式实例化放在类中的Dll.h中:

class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template<> void AClass::Func<float>(float&);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
};
class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
    template void AClass::Func<float>(float&);
};
类API\u类型AClass{
公众:
模板作废功能(T&data);
模板无效调用函数(T和数据){
Func(数据);
}
模板void AClass::Func(float&);
};
编译错误:错误C2252:模板的显式实例化只能在命名空间范围内发生

9) 在Dll.cpp中放入显式专门化:

编译错误:错误C2910:“AClass::Func”:无法显式专用化

我希望这足以证明我的努力。那么,在上述限制下,是否有机会修复“未解析的外部符号”?如果你忘了或根本没读过,限制是

Func
的模板实现必须是单独的 从其声明,即,不得在类声明或头文件中


如果您假设我不知道应该实例化模板函数,重复一下,我已经显式地实例化了
Func
,并以多种方式进行了尝试。所以编译器非常高兴,但是链接器抛出了错误“unresolved external symbol”。那么为什么链接器找不到已经实例化的模板成员函数呢?我还使用
dumpbin
检查了导入库DllProject.dll中的输出符号。符号
$Func@M@A类@@QEAAXAEAM@Z
它确实存在,就像地球向东旋转一样真实。那么,您知道如何主动跟踪链接器的行为,以找出为什么它无法找到函数位置而不是盲目猜测吗?非常感谢。

№6.出口指令应适用于:

template API_TYPE void AClass::Func<float>(float&);
模板API_TYPE void AClass::Func(float&);

显式实例化告诉编译器此变量在某个翻译单元中实例化,而export指令通知链接器它应该被导出/导入。

“都是关于模板类,而不是模板成员函数。”没有太大区别,定义必须出现在标题或包含所有实例化类型的显式链接单元中。您在exe项目中尝试过显式实例化吗?@john:同样的错误。我认为№6与显式实例化应该已经工作。可以使用导出指令,如
模板API_TYPE void AClass::Func(float&)@VTT:同样的错误。最重要的是,非常感谢您的回答!这个问题困扰了我好几天。我想添加两条注释:1)仅向类添加u declspec(dllexport)是不够的。要导出在.cpp中单独实现的实例化模板成员函数,我们仍然必须向模板函数声明中添加_declspec(dllexport),以便链接器能够找到它。。。2) 虽然我尝试过这种方法(#7)),但我没有幸看到它在我的机器上工作。然后我知道发生了什么。因为我在VS中工作,导入库是通过引用->DllProject链接的,而不是通过在链接器->附加依赖项列表中明确指定来链接的。设置这个引用的属性也是我的许多试验中的一个,但是其中一个没有被正确设置,我匆忙离开,因为我认为这个错误可能是由一些C++语言特定的原因引起的。所以保持头脑清醒是非常重要的,尤其是在解决诸如
class API_TYPE AClass {
...
};
template void AClass::Func<float>(float&);
template <class T> void API_TYPE Func(T& data);
class API_TYPE AClass {
public:
    template <class T> void Func(T& data);
    template <class T> void CallFunc(T& data) {
        Func<T>(data);
    }
    template void AClass::Func<float>(float&);
};
template API_TYPE void AClass::Func<float>(float&);