延迟加载DLL

3
为了简单起见,我将 DLL_TUTORIAL.dll 与头文件 MathFuncsDll.h 放在根目录 C:\ 中。
然后,创建一个空项目,并设置
Configuration Properties -> Linker -> Input -> Delay Loaded Dll's

C:\DLL_TUTORIAL.dll;%(DelayLoadDLLs)
以及
Configuration Properties -> VC++ Directories -> Include 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" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue 该项目仅包含 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:\Users\Tomek\Documents\Visual Studio 2010\Projects\clean_rough_draft\Release\clean_rough_draft.exe: 致命错误 LNK1120: 1个无法解析的外部

您能指出我的错误吗?


2
不支持导出模板方法。您必须将它们放在.h文件中。这会使您的DLL为空。 - Hans Passant
具体来说,模板方法并不是“真正”的方法 - 它们只是在编译时用于创建方法的模具。因此,模板方法不会编译成目标代码。 - nakiya
1个回答

3
问题与DLL的延迟加载无关。这里有两个问题:
1. 您正在导出模板函数。这样是行不通的,因为模板导出在Visual C++编译器中不被支持,并且已经从标准中删除。要使其正常工作,您有两个可能的解决方案: - 将方法实现移动到.h文件中,因此根本不需要DLL,因为所有代码都在头文件中。 - 使用您在客户端应用程序中使用的类型来实例化模板。这是通过在cpp文件中使用具有精确类型的实例化代码、在头文件中进行一些extern template声明等方式完成的。您可以在Google上搜索“extern template DLL”或类似的内容以获得更多信息。
2. 您仅在创建DLL时导出了方法,但从代码中看不到导入它们(或者至少我是这样看的)。您在每个方法前面使用__declspec(dllexport)告诉编译器将方法放在DLL中。当您想要从客户端应用程序中使用这些方法时,必须从DLL中导入它们。这是通过在每个方法前面放置__declspec(dllimport)来完成的。由于您不能同时使用这两个前缀,因此您只能创建两个几乎相同的头文件,这些头文件仅在该方法前缀方面略有不同,或者使用基于代码是DLL构建代码还是客户端应用程序的一些宏替换。再次提醒,您可以在Google上查找如何完成这项工作的更多信息。
希望这能帮到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接