We help IT Professionals succeed at work.

Odd Linker Error (LNK2019) With VS 2005 When Using Dll Built with VS 6.0

I'm new to Visual Studio 2005, and I'm encountering an odd linker problem.  Suppose I have a dll called "mydll" that contains a declaration (and implementation) of the following function:
--------------
#ifndef MYDLL_EXPIMP
  #ifdef MYDLL_EXPORTS
    #define MYDLL_EXPIMP __declspec(dllexport)
  #else
    #define MYDLL_EXPIMP __declspec(dllimport)
  #endif
#endif
void MYDLL_EXPIMP Test(WCHAR *wszValue);
--------------
If I build this dll using Visual Studio 6.0 and then attempt to build a separate application in Visual Studio 2005 that utilizes that dll (and its library file), I get an error like the following:

1>ApplicationFile.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl Test(wchar_t *)" (__imp_?Test ....(more)...

If I build the dll using Visual Studio 2005, the build-time error goes away, but my application crashes at runtime due to some bizarre threading loop that leads to a stack overflow.

I've never seen anything like this and my understanding is that library files (.lib) are supposed to be standards-based and fully compatible between versions and brands of development environments.

Can anyone tell me what's going on here?


mydll.h
 
#ifndef MYDLL_EXPIMP
  #ifdef MYDLL_EXPORTS
    #define MYDLL_EXPIMP __declspec(dllexport)
  #else
    #define MYDLL_EXPIMP __declspec(dllimport)
  #endif
#endif
 
void MYDLL_EXPIMP Test(WCHAR *wszValue);
===========
mydll.cpp
 
void MYDLL_EXPIMPT Test(WCHAR *wszValue)
{
  return;
}
===========
Consumer application includes header file #include where function is used and project references mydll.lib for linking.

Open in new window

Comment
Watch Question

CERTIFIED EXPERT
Top Expert 2009

Commented:
Try these :

mydll.h
---------
 
#ifndef MYDLL_EXPIMP
  #ifdef MYDLL_EXPORTS
    #define MYDLL_EXPIMP __declspec(dllexport)
  #else
    #define MYDLL_EXPIMP __declspec(dllimport)
  #endif
#endif
 
void MYDLL_EXPIMP Test(WCHAR *wszValue);


mydll.cpp
------------

#define MYDLL_EXPORTS
#include "mydll.h"
 
void MYDLL_EXPIMP Test(WCHAR *wszValue)
{
  return;
}
===========

Author

Commented:
In the project for the dll, MYDLL_EXPORTS is already defined.  I forgot to include one critical piece of information: The error only occurs if a method has unicode string pointer for a parameter.  So, for example:
void MYDLL_EXPIMP TestA(char *szText); <-- no problem
void MYDLL_EXPIMP TestW(WCHAR *wszText); <-- problem
CERTIFIED EXPERT
Top Expert 2009

Commented:
I'm not an expert on Visual Studio, but I wouldn't be surprised if there are compatibility isses between 6.0 and 2005. I'll let someone else with more knowledge about this take over ;)
CERTIFIED EXPERT
Top Expert 2009

Commented:
Just one more thing maybe : I assume you checked for typo's between the .h and the .cpp file ? Like the one you had in the code you posted : MYDLL_EXPIMPT vs. MYDLL_EXPIMP
evilrixSenior Software Engineer (Avast)
CERTIFIED EXPERT

Commented:
>> error LNK2019
I'm just wondering (guessing!), should the __declspec come before and not after the function return type?

e.g MYDLL_EXPIMP void Test(WCHAR *wszValue)

http://msdn2.microsoft.com/en-us/library/9h658af8(VS.80).aspx
http://msdn2.microsoft.com/en-us/library/dabb5z75(VS.80).aspx

>> If I build the dll using Visual Studio 2005, the build-time error goes away, but my application crashes at runtime due to some bizarre threading loop that leads to a stack overflow.
I strongly suspect this is unrelated to the linker issue. Can you provide any more information on this? Code example maybe?

>> my understanding is that library files (.lib) are supposed to be standards-based and fully compatible between versions and brands of development environments
Where ever did you get that idea? Some compilers aren't even compatible with themselves :)

-Rx
Senior Software Engineer (Avast)
CERTIFIED EXPERT
Commented:
>> my understanding is that library files (.lib) are supposed to be standards-based
There is no documented standard for the Application Binary Interface for C++. It is completely and utterly down to the vendor to pretty much make it up as they go along. For example, each compiler is free to implement name decorating as the vendor sees fit. This often doesn't even work between different versions of the same compiler! Try building C++ code on VC6.0 and then try and link to in on VC7.0 or greater and you'll find it probably won't link due to unresolved names. DLL's go someway to getting over this; however, if you are linking to the .lib DLL stub file to implicitly link to the DLL then this could be why the library you build on VC6.0 won't work with VC7.0! If so, you can get around this by explicitly loading the DLL using LoadLibrary(). You may be able to avoid explicit linkage if you can export your functions using C rather than C++ linkage. You need to wrap the declaration of your exported functions in an extern "C" block to give them C (undecorated) rather than C++ (decorated) linkage.

Example (untested) below: -

Some useful links that might help.
http://en.wikipedia.org/wiki/Application_binary_interface
http://msdn2.microsoft.com/en-us/library/253b8k2c.aspx
http://msdn2.microsoft.com/en-us/library/ms235636.aspx
http://msdn2.microsoft.com/en-us/library/d91k01sh(VS.80).aspx
http://msdn2.microsoft.com/en-us/library/28d6s79h(VS.80).aspx
mydll.h
 
#ifndef MYDLL_EXPIMP
  #ifdef MYDLL_EXPORTS
    #define MYDLL_EXPIMP __declspec(dllexport)
  #else
    #define MYDLL_EXPIMP __declspec(dllimport)
  #endif
#endif
 
extern "C" // Ensure the function has C linkage (it is exported undecorated).
{ 
   void MYDLL_EXPIMP Test(WCHAR *wszValue);
}
===========
mydll.cpp
 
void Test(WCHAR *wszValue)
{
  return;
}
===========
Consumer application includes header file #include where function is used and project references mydll.lib for linking.

Open in new window

Author

Commented:
Evilrix,
That answered my question.  The application crash that I described in the original ended up being because of an unrelated problem in my code that went undetected until I used VS 2005.

As for the linker problem, this raises some very interesting problems that I'll need to address.  The name decoration problem is one that I can't fix by using _stddecl because the methods that are having problems employ variable argument lists, so I need the caller to clean up the call stack after a function completes and returns.  However, because the name decoration changes between versions of Visual Studio, at the time I move my application to VS 2005, I'll have to recompile all dependent dlls at the same time that I do the main application.  And it now seems that if I was dependent on a third-party dll with a VS 6.0 library file, I'd be SOL. (or I'd have to do explicit run-time loading of the library and its methods)

Thank you for the info on this!

Author

Commented:
Thank you!

Explore More ContentExplore courses, solutions, and other research materials related to this topic.