链接静态库 Vs。 Linux 中的共享库

Posted

技术标签:

【中文标题】链接静态库 Vs。 Linux 中的共享库【英文标题】:Linking static library Vs. shared library in Linux 【发布时间】:2020-07-15 20:54:34 【问题描述】:

我正在阅读一本关于 Raspberry Pi 的书以了解 Raspberry Pi。

书中的一个项目展示了一个 C++ 类,它提供了访问 Raspberry Pi 上的 GPIO 的方法;类名是“gpio”。

书中讲述了使用这个类的两种方法:

    编写 C++ 代码,simple.cpp:在 simple.cpp 中,main 方法实例化 gpio 类并调用其公共方法。

    要编写 Python 代码:gpio.so 必须使用 Boost.python 创建。然后写simple.py,在里面导入gpio,调用它的public方法。

第一种方法很简单:将simple.cpp和gpio.cpp链接在一起,创建一个单独的exe。

对于后者,本书推荐使用 Boost.Python。

我下载了Boost包,调用bootstrap.sh和b2如下:

$ sudo ./bootstrap.sh --with-libraries=python --with-python-version=3.7
$ sudo ./b2 cxxflags=-fPIC -link=shared install

这些创建了 libboost_python37.so.1.73.0。

我尝试按如下方式构建 gpio.so:


PROG = gpio.so
CC = g++
CPPFLAGS = -c -fPIC -I/usr/include/python3.7m/ -I/usr/local/boost_1_73_0
LDFLAGS = -shared -pthread -L/usr/local/boost_1_73_0/bin.v2/libs/python/build/gcc- 
          8/release/python-3.7/threading-multi/visibility-hidden
LLIBS = -lboost_python37
OBJS = gpio.o

$(PROG) : $(OBJS)
  $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LLIBS)
gpio.o : gpio.h
  $(CC) $(CPPFLAGS) -c gpio.cpp

上面创建的 gpio.so 没有任何致命错误。

但如果我执行 'ldd gpio.so',它的输出会显示“libboost_python37.so.1.73.0 => not found”。

如果我运行 simple.py,它的输出显示“ImportError: libboost_python37.so.1.73.0: cannot 打开共享对象文件:没有这样的文件或目录”。

当我使用静态boost python库时,我可以完成上面的第二种方法:从python代码调用C++方法。

我的开发环境是在具有 4GB 内存的 Raspberry Pi 4 型号 B 上。操作系统是 Raspbian GNU/Linux 10 (buster)。开发软件包括:

    自 2020 年 7 月 15 日起的 Boost 包:修订版 1.73.0。 Python 3.7.3(32 位) g++ (Raspbian 8.3.0-6+rpi1) 8.3.0

【问题讨论】:

【参考方案1】:

我尝试按如下方式构建 gpio.so:

您的命令行告诉链接器如何在链接时找到libboost_python3.7.so。但它没有告诉运行时加载器如何在运行时找到那个库。

要告诉运行时加载器,请使用-rpath /path/to/library 链接器标志。那就是:

BOOST_LIB_PATH = /usr/local/boost_1_73_0/bin.v2/libs/python/build/gcc-8/release/python-3.7/threading-multi/visibility-hidden

LDFLAGS = ... -L $BOOST_LIB_PATH -Wl,-rpath,$BOOST_LIB_PATH ...

安装 libbost... 到系统目录实际上可能会更好,而不是从构建树中加载它。

【讨论】:

非常感谢您的回答。我尝试了 -rpath 但我没有将其识别为选项的 g++。在命令提示符处输入 'g++ -rpath' 会返回,“g++: error: unrecognized command line option '-rpath'”。 @JunBo 我已经编辑了答案:试试-Wl,-rpath,$BOOSR_LIB_PATH 不,它不起作用:在“-rpath”之后放置一个逗号。 g++ 不知道 '-rpath' 是什么。 @JunBo 你一定做错了什么。 -Wl,-rpath,/path/to/lib 应该是单个参数,没有空格。从那时起,所有版本的 GCC 都支持这一点。编辑您的问题以显示您尝试的 实际 命令,以及产生的错误是什么。 @Empployed 俄语 非常感谢。您的最后一条评论解决了这个问题。我在“Wl”和“-rpath”之间有一个空格,“-rpath”和“/path/to/lib”之间有一个空格。我没有意识到整个事情是一个“单一参数”。

以上是关于链接静态库 Vs。 Linux 中的共享库的主要内容,如果未能解决你的问题,请参考以下文章

C++ 静态库中的共享全局变量:Linux

将静态库链接到共享库(例如openmp)是一个好主意

静态库和共享库

linux共享库链接过程

静态库,链接到共享库

linux链接相关