链接 c++ 动态库一直失败

Linking c++ dynamic library keeps failing

本文关键字:一直 失败 动态 c++ 链接      更新时间:2023-10-16

我知道有很多关于它的帖子,但是我已经尝试过,但我仍然在链接我的库时收到错误。

在我当前的目录中,我创建了一个动态库

/bin/library_test.so

源代码和包含文件像往常一样在

./lib/ and ./src/

然后我正在尝试编译一个简单的 main.cpp并通过

g++ main.cpp -I/lib/ -L/bin/ -llibrary_test

但是我不断收到错误,例如"ExampleClass"未在此范围内声明,这意味着我没有链接库,对吗?由于此类包含在我的库中 cpp/头文件中。

我在链接中缺少某些内容,还是应该在我的主.cpp文件中添加一些包含命令?

在命令和设置中有几个内容需要检查。另请查看C++编译阶段。您需要了解这一点才能充分了解您的问题。

查看您发表的评论,您有 3 个主要问题:

  1. 编译(预处理后、组装和链接之前(
  2. 链接(编译器运行时仍在(
  3. 运行时链接(在执行已编译的二进制文件期间(

汇编

您收到的错误处于编译阶段,在链接二进制文件之前。此错误可能由于以下原因而生成:

  • 您忘记了定义ExampleClass的标头的#include

  • 您没有告诉编译器搜索标头的正确路径。在您的命令中,您告诉编译器搜索/lib(从文件系统根目录开始的目录(中的标头,而我很确定您想在相对于当前工作目录的目录中搜索它们,这意味着-Ilib -Isrc.

    顺便说一下,我强烈建议您将所有源文件放在src目录中,将所有标头放在include目录中,这通常在复杂的C/C++项目中完成。

连接

更正编译阶段后,您可能会遇到链接问题,因为您的库未遵循 linux 中用于共享对象的命名约定。库LIBRARYNAME的文件名应为libLIBRARYNAME.so

在某些情况下,您可能有多个版本的库,因此可以在so扩展名之后添加具有语义版本控制约定的版本(例如,libLIBRARYVERSION.so.2.1库的版本 2.1

(。要链接上述库,您必须使用-lLIBRARYNAME选项。

为了在链接时通知编译器在哪里可以找到库,您应该提供带有-L的路径,但此选项仅通知编译器,而不会在可执行文件中保存此类库的位置。

运行时链接

在这种情况下,有两种主要情况(我会有点草率,但只是为了指出正确的方向。完整的解释可能需要更多空间...和时间(:

  • 您可以使用rpath对二进制文件中共享库的位置进行硬编码,但是如果您分发应用程序,最终用户必须将 lib 放在您通过 rpath 指定的相同路径中,这就是我倾向于避免此解决方案的原因。
  • 现代 Linux 系统能够搜索所需的共享对象(这就是存在命名约定的原因(。搜索在受信任的目录中执行,搜索路径通过ldconfig配置文件(或$LD_LIBRARY_PATHenv 变量(进行配置。在搜索路径中安装新库时,应刷新运行时链接器的缓存(同样,这是通过ldconfig或重新启动完成的(。我强烈建议您阅读有关ldconfig的链接,因为它解释了如何配置新的搜索路径(例如/usr/local/lib(。

您可以通过命令ldd BINARY_NAME检查二进制文件是否能够找到所有必需的共享对象(在您的例子中为ldd a.out(。