【问题标题】:Unresolved external symbols issue未解决的外部符号问题
【发布时间】:2011-12-19 19:29:14
【问题描述】:

我有问题。我收到一个错误,但我不确定它为什么会发生。

2>Home.obj : error LNK2019: unresolved external symbol "**void __cdecl LogAString(char *,...)**" (?LogAString@@YAXPADZZ) referenced in function "**public: static void __cdecl X::Home::HomeStart(void)**" (?HomeStart@Home@X@@SAXXZ)
2>Widget.obj : error LNK2001: unresolved external symbol "void __cdecl LogAString(char *,...)" (?LogAString@@YAXPADZZ)
2>J:\src\out.dll : fatal error LNK1120: 1 unresolved externals

这是我的代码:

日志.h

#pragma once

#include <iostream>
#include <cstdarg>

void LogAString(char* fmt, ...);
void LogAnError(char* fmt, ...);

日志.cpp

#include "Log.h"

#include <Util/String/String Formatting.h> // defines format(). Does not have any errors or issues.

void LogAString(char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
};

void LogAnError(char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    auto formatted_string = format("ERROR: %s", fmt).c_str();
    LogAString(const_cast<char*>(formatted_string), ap);

    va_end(ap);
};

Home.cpp(提取)

#include "Home.h"
#include "Log.h"

namespace X {

void Home::HomeStart()
{
    while (true)
    {
        auto number_of_widgets = Widgets::Count();
        LogAString("Loading with %d widgets", number_of_widgets);
    }
}

} // namespace X

我以为我已经分别在头文件和 cpp 文件中声明和定义了函数。为什么我会收到这些错误?我已经做了几个小时了,但仍然不确定为什么会这样。在 VS 2010 上使用 VC++。

此时我没有使用任何其他外部库。编译目标是一个DLL,“out.dll”。

【问题讨论】:

  • 此日志内容是否在单独的项目中?
  • @FaileDev,它在同一个项目中。
  • 事实上,我确实编译了您的代码并执行了它,它运行良好。所以你要么有两个项目,要么正在发生一些神奇的事情......
  • 我认为这可能是 Visual Studio 的魔法。我之前遇到过这样的问题,通过创建一个相同的项目并编译来解决。我回家后试试看。

标签: c++ visual-studio-2010 visual-c++


【解决方案1】:

这是一个链接器错误,而不是编译器错误。这意味着您在代码中正确引用了头文件是正确的。事实上,您的代码编译成功。

但是,然后链接器出去寻找它所指向的库中的引用函数,然后空手而归。库引用在 VC++ 项目的属性表中定义。您的项目是否输出 Out.dll?看起来链接器需要一个。我会调查链接器部分以及您的编译生成的文件。

发布有关您的构建和解决方案/项目配置的更多信息,如果信息不足,甚至更准确地发布您的属性表中的内容。

【讨论】:

  • 我应该添加什么样的信息?我还想补充一点,此时我没有使用任何其他外部库。编译目标是一个DLL,“out.dll”。
  • 我现在没有启动我的 Windows 机器,但我认为我的 VC++ 项目实际上引用了它们自己的输出 dll。如果这是正确的,那么我将检查链接器部分中的路径与输出部分中的路径。路径中似乎应该有一个构建配置标志。 IE。您正在调试中构建,DLL 的输出将是 /Debug/Out.dll。不过,我认为默认情况下这是正确设置的。这让我想知道 FailedDev 是否​​不正确,实际上您正在尝试将第二个库链接到包含 LogAsString 的库。
  • 哦,我不知道它引用了自己。我不想链接第二个库。一切都是独立的,我在编译这个库时遇到了错误。
  • 我刚刚启动了一个 Windows 环境来确认这一点。在我的一个 DLL 的属性表下(查看原始 XML 而不必浏览 GUI)我有一个 VCLinkerTool 部分,其中包含一个 AdditionalDependencies 节点,该节点具有 mylibrary.lib 和一个 AdditionalLibraryDirectories 节点,该节点设置为 &(SolutionDir )\x64\$(配置名称)。也许编译静态库和动态库是不同的,但值得一试。我认为这两个属性都在链接器部分下。
  • 显然,路径中间的 x64 目录是特定于平台的。而且我敢肯定,您可能有一个完全不同的输出路径,它不依赖于这些变量。我认为重要的是确保 Out.dll 的路径正确。
【解决方案2】:

您还记得在您的项目中添加Log.cpp 吗?

如果是这样,则在十六进制编辑器中打开文件log.obj。搜索字符串LogAnError。它将成为较大装饰字符串的一部分。 Use the undname command to undecorate it。将其与链接器无法解析的内容进行比较。找出差异并修复您的 LogAnError 函数,使它们再次匹配。

【讨论】:

  • 谢谢!出于某种奇怪的原因,Visual Studio 的 GUI 说 Log.cpp 包含在项目中。但是,当我查看 VS 提供的 MSBuild 输入时,Log.cpp 被省略了!我挠了挠头,又检查了三次,确实是这样。手动将文件添加到列表中。谢谢!
【解决方案3】:

也许命名空间与它有关,没有命名空间 X 是否可以工作?

【讨论】:

  • 如果您只是猜测,那么您应该发表评论,而不是答案。
  • 好的,感谢您的提醒。我会记住这一点。我相对较新,所以我仍然对做事的最佳方式有所了解。
【解决方案4】:

好的,根据您的评论:

编译目标是一个DLL,“out.dll”

我假设您在其他项目中使用这个 out.dll。当您尝试执行此操作时,您会收到上述链接器错误。如果是这种情况,这是因为您没有导出函数。此外,拥有这样的全局函数是一种不好的做法。您至少应该将它们包装在某个类中,例如实用程序或其他东西并将它们声明为静态:

示例 Log.h:

#pragma once

#include <iostream>
#include <cstdarg>

class __declspec (dllexport) Utils
{
    public:
          static void LogAString(char* fmt, ...);
          static void LogAnError(char* fmt, ...);
};

Log.cpp 应该几乎保持不变。

#include "Log.h"

#include <Util/String/String Formatting.h> // defines format(). Does not have any errors or issues.

void Utils::LogAString(char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
};

void Utils::LogAnError(char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    auto formatted_string = format("ERROR: %s", fmt).c_str();
    LogAString(const_cast<char*>(formatted_string), ap);

    va_end(ap);
};

现在,当您使用 .dll 时,您的函数将被导出并可用于您的其他项目。您还应该在包含目录中包含 Log.h 文件,并确保“out.dll”位于主项目的同一输出文件夹中。此外,您应该将 out.lib 添加到其他库中。

希望这是您的问题。下次提供更多细节。

【讨论】:

  • 我没有使用其他项目;我在编译库本身时遇到了错误。
  • @alan 那么你没有向我们展示你应该展示的东西。你的代码编译。
  • 这就是我所有的代码。我将在具有相同设置的新项目中再次尝试。 Perhaa Visual Studio 像以前一样再次扮演我。 (两个相同的项目。一个编译,另一个不编译)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 2010-11-20
  • 1970-01-01
  • 2020-10-15
  • 2011-10-21
相关资源
最近更新 更多