3

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

然后,创建空项目,设置

Configuration Properties->Linker->Input->Delay Loaded Dll's

C:\DLL_TUTORIAL.dll;%(DelayLoadDLLs)

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

C:\;$(包含路径)

编译器命令:

/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 的文件。

主文件

#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 unresolved externals

你能指出我的错误吗?

4

1 回答 1

3

该问题与是否延迟加载 DLL 无关。我可以在这里看到两个问题:

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

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

我希望这会有所帮助。

于 2012-08-22T05:54:43.553 回答