1
votes

I have a library (dll) which exposes a class along with its constructors which are supposed to be used in other modules (exe and dll). I am able to instantiate that class from other library modules but not exe modules. I get the linker error - 'error LNK2019: unresolved external symbol' during linking. I am confused why linking succeeds when used in other library projects and not exe project. Can somebody help me with this?

the following is the class declaration:

class __declspec(dllimport) MyException
{
public:
MyException(unsigned int _line, const char *_file, const char *_function, MyExceptionType _type, const wchar_t* _message = 0, ...);
};

This is the whole error: error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl MyException::MyException(unsigned int,char const *,char const *,enum MyException::MyExceptionType,unsigned short const *,...)" (_imp??0MyException@@QAA@IPBD0W4MyExceptionType@0@PBGZZ) referenced in function "public: __thiscall MyClassUsesMyException::MyClassUsesMyException(class SomeClass *,int)" (??0MyClassUsesMyException@@QAE@PAVSomeClass@@H@Z)

MyClassUsesMyException is being instantiated in 'MyApp.cpp'.

Thanks, Rakesh.

1

1 Answers

0
votes

Update: wchar_t Not Always Native

After a fairly long exchange of information and getting a little more info from the OP, the problem is essential this:

class __declspec(dllimport) MyException
{
public:
    MyException(unsigned int _line, 
        const char *_file, 
        const char *_function, 
        MyExceptionType _type, 
        const wchar_t* _message = 0, // <<== note wchar_t type
        ...);
};

Visual C++ can be configured to either treat wchar_t as a native type or not. When not treated as a native type, unsigned short is the specified macro substitution for wchar_t. The linker was complaining about the above function being unresolvable, but what really caught my eye was this at the tail of the undefined symbol:

,unsigned short const *,...)

Note the unsigned short. This hinted to me that the compiler was using non-native wchar_t when compiling the EXE. I considered it possible that maybe the DLL was compiled with wchar_t configured as native, thereby introducing a different signature and thus not matching up at link time.

If you're surprised this was the problem, imagine how surprised Rakesh and I were =P


Original Answer

That class should be in a single common header with preprocessor logic to determine proper import/export state of the declaration. Like so:

MyDLL.h

#ifndef MYDLL_H
#define MYDLL_H

// setup an import/export macro based on whether the 
//  DLL implementing this class is being compiled or
//  a client of the DLL is using it. Only the MyDLL.DLL
//  project should define MYDLL_EXPORTS. What it is 
//  defined as is not relevant. *That* it is defined *is*.

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

class MYDLL_API MyException
{
    // your class definition here...
};

#endif

Then, in your DLL project that implements the exception (and only in that project), add MYDLL_EXPORTS to the preprocessor defines list in your project configuration.