3

For simplicity, I've placed both DLL_TUTORIAL.dll with header MathFuncsDll.h in the root folder C:\ .

Then, created the empty project, setting

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

to

C:\DLL_TUTORIAL.dll;%(DelayLoadDLLs)

and

Configuration Properties->VC++ Directories->Include Directories

to

C:\;$(IncludePath)

Complier commands:

/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

This project contains only the file with 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 has been compiled successfully in different solution.

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);

    };


}

Definitions of these functions:

#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; 
    }
}

Running this program fails:

1>main.obj : error LNK2001: unresolved external symbol "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 : fatal error LNK1120: 1 unresolved externals

Could you point out my mistake?

0x6B6F77616C74
  • 2,559
  • 7
  • 38
  • 65
  • 2
    Exporting template methods is not supported. You'll have to put them in the .h file. Which leaves you with an empty DLL. – Hans Passant Aug 22 '12 at 01:06
  • To elaborate, Template methods are not "real" methods - they are just molds used to create methods at compile time. Hence template methods do not compile into object code. – nakiya Aug 22 '12 at 03:42

1 Answers1

3

The problem has nothing to do with delayed loading of the DLL or not. I can see two problems here:

  1. You are exporting templated functions. This wouldn't work that way because template exporting is not supported in Visual C++ compiler and however has already been dropped from the standard. For this to work you have two possible solutions:

    • Move the implementations of the methods in the .h file, thus no longer needing a DLL at all as all the code is in a header file;
    • Instantiate the templates with the types that you will use in your client application. This is done be putting instantiation code with exact types in your cpp file, doing some extern template declarations in the header, etc. You can look that up in Google for more information, just search for 'extern template DLL' or something similar.
  2. You only export the methods when creating the DLL, but never import them (or at least that's what I see from the code). You use __declspec(dllexport) in front of each method, which tells the compiler to put that methods in the DLL. When you want to use these methods from a client application, you have to import them from the DLL. This is done by placing __declspec(dllimport) in front of each method. Since you can not put both prefixes on the methods you either have to create two almost the same header files that just differ on that method prefix thing or use some macro substitution based on whether this is a DLL building code or a client application. Once again, you can look that up in Google to see how its done.

I hope that helps.

Lyubomir Vasilev
  • 3,000
  • 17
  • 24