使用dllimport / dllexport宏在多个项目中包含标头时VC ++链接器错误

时间:2018-03-28 12:05:56

标签: c++ linker dllimport dllexport unresolved-external

我使用Visual Studio 2017解决方案,其中包含5个项目:

  • SpikeConfig
  • SpikeEngine
  • SpikeRenderer
  • SpikeUI
  • SpikeUtils

在SpikeUtils中,我有一个标题_SpikeEngineObject.h:

#pragma once

#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif

#include "GUID.h"

namespace SpikeUtils
{
    class SPIKEUTILS_EXPORT _SpikeEngineObject
    {
    public:
        const std::string & _SpikeEngineId()
        {
            return _SpikeRef.Value();
        }
    private:
        SpikeUtils::GUID _SpikeRef = SpikeUtils::GUID::Generate();
    };
}

包含的文件GUID.h如下所示:

#pragma once

#include <iostream>

#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif

namespace SpikeUtils
{
    class SPIKEUTILS_EXPORT GUID final
    {
    public:
        GUID(GUID const & other) = default;
        GUID& operator=(GUID& other) = default;

        static GUID Generate();
        std::string const & Value();
    private:
        GUID(std::string const & value) : value(value)
        {}
        std::string value;
    };
}

我省略了GUID.cpp的实现,因为我认为它并不相关。

现在,在SpikeUI中,我有一个类Drawable,它只是继承自_SpikeEngineObject.h

 #pragma once

 #include "_SpikeEngineObject.h"

 #ifdef DLL_SPIKEUI
 #define SPIKEUI_EXPORT __declspec(dllexport)
 #else
 #define SPIKEUI_EXPORT __declspec(dllimport)
 #endif

 namespace SpikeUI
 {
     namespace UI
     {
         struct SPIKEUI_EXPORT Drawable : SpikeUtils::_SpikeEngineObject
         {
             ....
         };
     }
 }

显然,所有相应的DLL_定义都已放在每个单独的项目的C / C ++中 - &gt;预处理器 - &gt;预处理器定义,因此项目应使用适当的dllimport / dllexport宏构建。

但是当我尝试构建SpikeUI时,我会收到链接器错误,如:

LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl 
SpikeUtils::_SpikeEngineObject::_SpikeEngineObject(void)" (__imp_?? 
0_SpikeEngineObject@SpikeUtils@@QEAA@XZ) referenced in function "public: 
__cdecl SpikeUI::UI::Drawable::Drawable(enum SpikeUI::UI::DrawableType)" (?? 
0Drawable@UI@SpikeUI@@QEAA@W4DrawableType@12@@Z)

LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl 
SpikeUtils::_SpikeEngineObject::~_SpikeEngineObject(void)" (__imp_?? 
1_SpikeEngineObject@SpikeUtils@@QEAA@XZ) referenced in function "int 
`public: __cdecl SpikeUI::UI::Drawable::Drawable(struct UI::Drawable::dtor$0 
const &)'::`1'::dtor$0" (?dtor$0@?0???0Drawable@UI@SpikeUI@@QEAA@AEBU012@@Z@4HA)

一个有趣的事实是,Visual Studio甚至会突出显示将使用哪个宏,例如GUID.h会突出显示dllexport宏,但_SpikeEngineObject.h会因某种原因突出显示dllimport宏。

通过SO和MSDN搜索,看起来这个宏模式应该可行,但由于某种原因,它在我的项目中不一致。

如何解决链接器错误?

1 个答案:

答案 0 :(得分:0)

在这里回答我自己的问题:

SpikeUI 项目依赖于 SpikeUtils 项目,并且它与.lib和.dll项目相关联,该项目通过构建 SpikeUtils而输出项目。

现在,问题是类 _SpikeEngineObject 是一个仅限标题的类(即该类没有.cpp)。因此,我假设 SpikeUtils.lib 不包含 _SpikeEngineObject 的构造函数/析构函数等的任何符号,因此链接器在链接时遇到问题。 / p>

我通过为类添加.cpp文件并实现哑构造函数/析构函数来解决问题,以便编译器生成这些符号,一切都很好。