2012-08-22 73 views
3

为了简单起见,我将DLL_TUTORIAL.dll和头文件MathFuncsDll.h放在根文件夹C:\中。延迟加载DLL

然后,创建空的项目,设置

配置属性 - >连接器 - >输入 - >延迟加载的DLL的

C:\ DLL_TUTORIAL .dll;%(DelayLoadDLLs)

配置属性> VC++ Directories->包含目录

C:\; $(INCLUDEPATH)

编者命令:

/Zi/nologo/W3/WX-/O2/Oi/Oy-/GL/D“_MBCS”/ Gm-/EHsc/MT/GS /Gy/fp:precise/Zc:wchar_t/Zc: forScope /Fp"Release\clean_rough_draft.pch “/法 ”发布\“/ FO ”发布\“ /Fd"Release\vc100.pdb”/ GD/analyze-/errorReport:队列

该项目只包含带有main的文件。

的main.cpp

#include <Windows.h> 
#include <iostream> 
#include "MathFuncsDll.h" 

using namespace MathFuncs; 
using namespace std; 

int main() 
{ 
    std::cout<< MyMathFuncs<int>::Add(5,10)<<endl; 

    system("Pause"); 
    return 0; 
} 

的Dll已经在不同的解决方案成功编译。

MathFuncsDll.h

namespace MathFuncs 
{ 
    template <typename Type> 
    class MyMathFuncs 
    { 
    public: 
     static __declspec(dllexport) Type Add(Type a, Type b); 

     static __declspec(dllexport) Type Subtract(Type a, Type b); 

     static __declspec(dllexport) Type Multiply(Type a, Type b); 

     static __declspec(dllexport) Type Divide(Type a, Type b); 

    }; 


} 

这些函数定义:

#include "MathFuncsDll.h" 

#include <stdexcept> 

using namespace std; 

namespace MathFuncs 
{ 
    template <typename Type> 
    Type MyMathFuncs<Type>::Add(Type a,Type b) 
    { return a+b; } 

    template <typename Type> 
    Type MyMathFuncs<Type>::Subtract(Type a,Type b) 
    { return a-b; } 

    template <typename Type> 
    Type MyMathFuncs<Type>::Multiply(Type a,Type b) 
    { return a*b; } 

    template <typename Type> 
    Type MyMathFuncs<Type>::Divide(Type a,Type b) 
    { 
     if(b == 0) throw new invalid_argument("Denominator cannot be zero!"); 
     return a/b; 
    } 
} 

运行该程序失败:

1> main.obj:错误LNK2001:解析的外部符号“ public:static int __cdecl MathFuncs :: MyMathFuncs :: Add(int,int)“(?Add @?$ MyMathFuncs @ H @ MathFuncs @@ SAHHH @ Z) 1> C:\用户\托梅克\文档\ Visual Studio 2010的\项目\ clean_rough_draft \发布\ clean_rough_draft.exe:致命错误LNK1120:1周无法解析的外部

你能指出我的错误?

+2

不支持导出模板方法。你必须把它们放在.h文件中。这留下了一个空的DLL。 –

+0

详细说明,Template方法不是“真正的”方法 - 它们只是在编译时用于创建方法的模具。因此模板方法不能编译成目标代码。 – nakiya

回答

3

该问题与DLL的延迟加载或没有任何关系。我可以在这里看到两个问题:

  1. 您正在导出模板化函数。这不会以这种方式工作,因为模板导出在Visual C++编译器中不受支持,但是已经从标准中删除。为此,您有两种可能的解决方案:

    • 移动.h文件中方法的实现,因此不再需要DLL,因为所有代码都在头文件中;
    • 使用您将在客户端应用程序中使用的类型实例化模板。这样做的目的是在你的cpp文件中添加实例化代码,并在头文件中执行一些extern template声明等。你可以在Google上查看更多信息,只需搜索'extern template DLL'或类似的东西即可。
  2. 您只在创建DLL时导出方法,但从不导入它们(或者至少这是我从代码中看到的)。在每个方法前使用__declspec(dllexport),它告诉编译器将该方法放入DLL中。当你想从客户端应用程序使用这些方法时,你必须从DLL中导入它们。这是通过将__declspec(dllimport)放置在每种方法的前面来完成的。既然你不能在这两个方法上放置两个前缀,你必须创建两个几乎相同的头文件,这些头文件只是在方法前缀上有所不同,或者根据这是DLL构建代码还是客户端应用程序,使用一些宏替换。再次,您可以在Google中查看它的完成情况。

我希望有帮助。