【问题标题】:C++ Project compiles as static lib, fails (linker error) as dynamic lib. why?C++ 项目编译为静态库,失败(链接器错误)为动态库。为什么?
【发布时间】:2011-02-20 08:54:03
【问题描述】:

我有一个 VS2008 原生 C++ 项目,我希望将其编译为 DLL。

它只引用一个外部库(log4cplus.lib),并使用它的功能。 (自然也使用 log4cplus 的 .h 文件)。

当我尝试将我的项目编译为静态库时,它成功了。 当我尝试作为 DLL 时,它失败了:

1>MessageWriter.obj : error LNK2019: unresolved external symbol "public: static class log4cplus::Logger __cdecl log4cplus::Logger::getInstance(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > const &)" (?getInstance@Logger@log4cplus@@SA?AV12@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z) referenced in function "class log4cplus::Logger __cdecl Log(void)" (?Log@@YA?AVLogger@log4cplus@@XZ)

还有 4 个与 log4cplus.lib 中的函数相关的错误。

这似乎真的很愚蠢..请帮助我:)

谢谢!

编辑:

我链接到 log4cplus.lib 文件,它发现它很好。 此外,log4cplus.lib 是 100% 功能的,我在另一个项目中使用它没有问题。 我的初衷是将我的项目编译为一个静态库并在我正在编写的另一个 DLL 中使用它,但是当这样做时,我在另一个项目中得到相同的链接器错误......

编辑#2:

导致链接器错误的函数是静态函数。这可能是问题的一部分吗?

【问题讨论】:

    标签: c++ dll visual-studio-2008-sp1 log4cplus


    【解决方案1】:

    wilx 是对的。我也有同样的链接问题。

    我花了将近一天的时间来解决这个问题。

    我已经下载了log4cplus-1.0.4,用visual studio 2010打开这个项目后,编译,静态库和动态库都没有报错。

    但是,当我尝试使用这些库时,无论是静态库还是动态库,都会出现链接错误。

    原因是,默认情况下,这些项目使用多字节字符,但是,我自己的项目使用 unicode,所以,为了解决这些链接问题,你只需要更改一个项目的字符集。

    unicode 或多字节字符集。

    并在 Visual Studio 2010 中更改一个项目的字符集, 请参阅以下链接。

    How do I turn off Unicode in a VC++ project?

    【讨论】:

      【解决方案2】:

      当您创建静态库时,库创建者不会尝试解析您正在使用的所有函数(log2cplus.lib 中的函数)。当您创建一个与您的静态库链接的可执行文件时,这些函数将被解析。

      当您创建动态库时,库创建者(链接器)会尝试解析您正在使用的所有函数。构建动态库后,您必须立即为链接器提供 log4cplus.lib 库。您不能等到创建可执行文件。

      【讨论】:

      • 我已经为它提供了 log4cplus.lib.... 我已经将它添加到项目属性的“链接器”部分...
      • 它确实找到了文件……正如我在下面所说的那样……它只是由于某种原因无法识别其中的某些功能……
      【解决方案3】:

      在任何一种情况下,您都需要链接库。

      不同之处在于,当您静态链接时 - 所有功能都通过您正在使用的库链接。

      当您动态链接时,您会链接到具有从 dll 加载和使用函数的功能的导入库,而您缺少此步骤。通常导入库与您链接的 dll 具有相同的名称。

      编辑:

      我看到缺少的符号不是 '__imp...' 这意味着没有为动态链接“配置”头文件,可能是因为在包含 Log4Cplus 头的项目中未定义 LOG4CPLUS_BUILD_DLL 或 log4cplus_EXPORTS 或 DLL_EXPORT。

      【讨论】:

      • 我应该把DLL放在哪里?
      • 不应该只在运行时加载DLL吗?为什么链接器会试图找到它?
      • 对,但是您需要一些信息什么 dll 以及如何访问它,因为它有导入库。我想我知道出了什么问题 - 请参阅我的更新。
      • 我不明白,我应该将此表达式添加到我的代码中吗?我应该把它放在哪里?我搜索了它,在我的整个项目中都找不到它......
      • 换一种方式:与以静态或动态方式使用 log4cplus 的情况有何不同 - 之后更容易看出哪里做错了。?
      【解决方案4】:

      您实际上是在链接 log2cplus.lib 文件吗?如果您正在编译为静态库,那么您将通过最终的 .exe 链接到它,而不是在静态库中 - 也许这就是区别?

      【讨论】:

      • 是的,它确实找到了文件(当我将库名称更改为虚假编译时立即失败)......我不明白为什么它在 log4cplus 中找不到这些函数.lib... :(
      • 请再次解释您在回答中的意思...如果我将此项目编译为静态库 - 那么我不应该链接到 log4cplus.lib 吗?我只会在使用静态库的 .exe 项目中链接 log4cplus.lib?
      • 不,DLL 应该链接到 log4cplus.lib,正如你所说的那样 - 我很困惑为什么它找不到符号。当你的项目是一个静态库时,你是否真的链接了一个最终的 .exe 来测试一切是否正常?
      • 产生链接器错误的函数是静态函数。这可能是问题吗?
      • 静态类函数还是静态 C 函数?如果是后者,那就可以解释了,但是我也看不到原始静态库如何看到这些函数。
      【解决方案5】:

      你使用了 __declspec(dllimport) 和 __declspec(dllexport) 吗?

      链接静态库时不需要它们,但 DLL 需要它们。该函数必须声明为导出(在 DLL 中),因此用户可以在外部使用它(从而从 DLL 中导入它)。

      也许这会有所帮助:

      使用 __declspec(dllimport) 导入应用程序

      http://msdn.microsoft.com/en-us/library/8fskxacy%28VS.80%29.aspx

      最好的问候

      【讨论】:

        【解决方案6】:

        如果您使用的是 MSVC 之类的编译器,那么在从 lib 更改为 dll 时,它可能在您不知道的情况下更改了项目设置。您应该仔细检查,在 DLL 模式下,您已正确链接到 lib。

        【讨论】:

          【解决方案7】:

          我可以看到链接器错误有两种可能性:

          1. 您已经使用提供的 Release 构建配置编译了 log4cplus.dll(以及关联的 log4cplus.lib 导入库),但现在您的应用程序编译时将“字符集”选项设置为“使用 Unicode 字符集”

          2. 或者您正在尝试使用 log4cplus 的静态库,但为您的应用程序定义了 LOG4CPLUS_BUILD_DLL。

          我赌的是 1 号。不过,它可能是别的东西。你用的是什么版本的 log4cplus?

          如果您想在应用程序中使用 log4cplus.dll,请定义 LOG4CPLUS_BUILD_DLL 符号。 log4cplus_EXPORTS 和 DLL_EXPORT 仅支持基于 CMake 的构建系统,以及分别在 MingGW 上基于 autotools 的构建系统。

          【讨论】:

            猜你喜欢
            • 2011-09-22
            • 1970-01-01
            • 1970-01-01
            • 2014-03-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多