函数调用如何在某些地方导致未解析的外部,而不是其他地方?

时间:2017-06-23 23:37:08

标签: c++ linker unresolved-external

我已经阅读了关于未解决的外部因素的许多答案,但只有一个似乎接近我的情况(Unresolved external symbol for some function calls but not all),但答案没有帮助。

这是我的情况:我正在使用VS 2015并编译一个使用多个静态库的.dll。 (所有库都是我的VS'项目'的一部分 - 这意味着我可以控制所有代码 - 我还没有使用其他来源的库。)

顺便说一句,我在这里使用的术语“库”非常松散。这些都是我的VS'解决方案'中的C ++'项目',它们创建了静态库,但它们主要用于代码组织。它们并不打算用于其他项目或其他编码组。

我有一个可以在库代码中调用的全局函数。声明在一个头文件中,我#include我想要使用该函数(头文件使用#pragma once和#ifndef guards)。定义在.dll代码中。

这是我不明白的:如果我在我的库中定义的类的某些中使用全局函数,我将得到一个未解决的外部错误。但是,我可以注释掉该行,并且.dll将编译,链接,与代码中的其他位置,来自同一个“库”,成功使用全局函数,以相同的方式调用。我使用一个简单的控制台应用程序运行代码,并且使用全局函数的位置确实从它获得适当的返回。因此,全局函数确实得到了正确解决。

从我读过的关于'未解决的外部'错误的内容来看,在我看来,链接器应该能够解析引用,或者不能。如果没有,则不应该对全局函数的任何调用导致未解析的外部函数,并保持代码不被链接?

我觉得我在这里缺少一些基本的东西。我不太确定如何解决这个问题。 Instinct说比较它工作的代码(全局函数调用不会导致链接器错误)与它没有的地方。但是,我看不出链接视角的差异。所有使用全局函数的文件都必须包含带有函数声明的头文件(他们会这样做)(或编译器会抱怨)。

欢迎任何想法,建议或见解。如果你做到这一点,那么,谢谢你的时间!

以防实际错误可能有用,这里是:

WindogEngineLibd.lib(ColumnFinder.obj) :
error LNK2019: unresolved external symbol "class IUserPreferences & __cdecl global_user_prefs::GetUserPreferences(void)" (?GetUserPreferences@global_user_prefs@@YAAEAVIUserPreferences@@XZ) referenced in function "public: class std::vector<struct std::pair<class std::weak_ptr<class CDataColumn const >,class std::weak_ptr<class CDataColumn const > >,class std::allocator<struct std::pair<class std::weak_ptr<class CDataColumn const >,class std::weak_ptr<class CDataColumn const > > > > __cdecl CColumnFinder::EvaluateDualExpressions(class CColumnExpression,class CColumnExpression)const " (?EvaluateDualExpressions@CColumnFinder@@QEBA?AV?$vector@U?$pair@V?$weak_ptr@$$CBVCDataColumn@@@std@@V12@@std@@V?$allocator@U?$pair@V?$weak_ptr@$$CBVCDataColumn@@@std@@V12@@std@@@2@@std@@VCColumnExpression@@0@Z)

编辑1

我要添加一些伪代码(希望)让我的情况更清楚。

静态库1中的FileA.h(包含所需的头文件)

float GlobalFunction();
静态库2中的

FileB.cpp(使用GlobalFunction的一个类的.cpp文件)

#include FileA.h;

float ClassWidget::UseGlobalValue()
{
    return GlobalFunction() * 2.0f; // no problem with this line
}

静态库2中的FileC.cpp(尝试使用GlobalFunction的另一个类的.cpp文件,与ClassWidget在同一个库中)

#include FileA.h;

float ClassThingy::TryToUseGlobalValue()
{
    return GlobalFunction() * -1.0f; // uncommenting this line will cause link error
}

在.dll项目中,我包含相同的头文件:

FileDll.h

#include FileA.h;

然后定义函数:

FileDll.cpp

float GlobalFunction()
{
    return 2.0f;
}

如果我在FileDll.cpp中注释掉'GlobalFunction'的定义,那么在编译.dll时,对'GlobalFunction'的所有调用都会导致未解决的外部错误。有了它,所有错误都得到了解决(包括ClassThingy中的错误)。

当我在控制台应用程序中尝试使用我的.dll时,ClassThingy中对GlobalFunction的调用会导致链接错误,而ClassWidget中的调用则不会。

我很确定这与.dll链接的方式有关,但我无法弄清楚如何。如果我创建一个直接使用静态库的控制台应用程序,并让它定义'GlobalFunction' - 一切都很好,没有链接错误。如果控制台应用程序是我的目标,我就是这么做的。但是,.dll是我的目标 - 控制台应用程序仅用于测试。

我研究过使用'extern'关键字,但据我所知,这对于文件范围的函数来说是多余的。

再次感谢您的帮助,见解。

0 个答案:

没有答案