Visual Studio 2013 dll export linkage error (LNK20

2019-06-26 11:28发布

问题:

I know similar question has been asked before, but it looks like there is something different in what concerns classes export than a simple function ... I have checked all those solutions, checked all the suggestions but it still looks like I am missing something ...

What's happening:

  • I have a master C++ project written in Visual Studio 2013 and I want to add a dll library with various utils. I have created a dummy one, with basically no functionality, but it fails to compile:
    2>  TestSvc_i.c
    2>TestSvc.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall CUtils::CUtils(void)" (__imp_??0CUtils@@QAE@XZ) referenced in function _wWinMain@16
    2>C:\Work\TestSvc_root\Debug\TestSvc.exe : fatal error LNK1120: 1 unresolved externals
    ========== Rebuild All: 1 succeeded, 1 failed, 0 skipped ==========

And the code in the main project looks like this:

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
    CUtils *a = new CUtils();
    delete a;

    return 1;
}

I have the following setup:

  • the master project written in C++ with Visual Studio 2013;
  • I am using Unicode charset and the runtime is used in a shared dll;
  • _UNICODE is defined;
  • SubSystem: Windows (/SUBSYSTEM:WINDOWS);
  • I want to create an utility library that should be used in a shared dll. The code looks like this:

Utils.h:

#ifdef UTILS_EXPORTS
#define UTILS_API __declspec(dllexport)
#else
#define UTILS_API __declspec(dllimport)
#endif

// This class is exported from the Utils.dll
class UTILS_API CUtils {
public:
    CUtils(void);
};

Utils.cpp:

#include "stdafx.h"
#include "Utils.h"

// This is the constructor of a class that has been exported.
// see Utils.h for the class definition
CUtils::CUtils()
{
    return;
}
  • I checked the dll-project settings and basically, they're all as in main project;
  • UTILS_EXPORTS is defined in dll-project so normally, all definitions should have __declspec(dllexport) (as expected, not defined in UTILS_EXPORTS);
  • I have the following preprocessor definitions: WIN32;_DEBUG;_WINDOWS;_USRDLL;UTILS_EXPORTS;
  • dll-project is added as a dependency to master-project;
  • the dll is copied under $(SolutionDir)\Debug but not under $(SolutionDir)\$(MasterProject)\Debug - I don't know why. I manually copied it, but I still have the same problem;
  • I ran DUMPBIN utility on Utils.dll and here is how it looks:
    C:\Work\TestSvc_root\Debug>DUMPBIN /EXPORTS /SYMBOLS Utils.dll
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.


    Dump of file Utils.dll

    File Type: DLL

      Section contains the following exports for Utils.dll

    00000000 characteristics
    53C632A8 time date stamp Wed Jul 16 10:07:04 2014
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00011154 ??0CUtils@@QAE@XZ = @ILT+335(??0CUtils@@QAE@XZ)
          2    1 000110C8 ??4CUtils@@QAEAAV0@ABV0@@Z = @ILT+195(??4CUtils@@QAEAAV0@ABV0@@Z)

    Summary

        1000 .data
        1000 .idata
        2000 .rdata
        1000 .reloc
        1000 .rsrc
        4000 .text
       10000 .textbss
  • I have tried to "sniff" the value of UTILS_API:
    #define DO_QUOTE(X)        #X
    #define QUOTE(X)           DO_QUOTE(X)
    #define MY_QUOTED_VAR      QUOTE(MYVARIABLE)

    #pragma message(QUOTE(UTILS_API))

which dumps the correct value: when "used" from dll, it dumps __declspec(dllexport), and when used from main-project it dumps __declspec(dllimport)

So, any hint? It looks like there is something that has to do with class export definition/method decoration ... In previous plain old Visual C++ there used to be a "def" file where you could map the exported names ... but in this new version, I am lost.

Thanks!

回答1:

As a workaround, you may explicitly add .lib file (generated during the build of your .dll) to the list of input libraries in the linker options of the main project.