我正在从我在这里C++ Dynamic Shared Library on Linux的示例中的类创建共享库。我想从创建的共享库中调用另一个共享库,然后在主程序中使用它。所以我有myclass.so库,我想从myclass.so库中调用另一个库,例如anotherclass.so,然后在主程序中使用此myclass.so库。请问我该怎么做。
答案 0 :(得分:2)
可以通过多种方式将多个共享库添加到 程序的链接(如果要构建所有库和程序), 你自己。
基本方法是将所有库显式添加到 程序的链接,如果只构建 程序和由另一方建立的链接库。
如果链接中的对象文件foo.o
依赖于库libA.so
,则
在链接顺序中,foo.o
应该在libA.so
之前。同样,如果libA.so
取决于libB.so
,则libA.so
应该在libB.so
之前。这是一个例子。
我们将从文件中创建共享库libsquare.so
:
square.h
#ifndef SQUARE_H
#define SQUARE_H
double square(double d);
#endif
和
square.cpp
#include <square.h>
#include <cmath>
double square(double d)
{
return pow(d,2);
}
请注意,函数square
会调用pow
,该函数在
标准标头<cmath>
,并在数学库libm
中定义。
将源文件square.cpp
编译为与位置无关的目标文件
square.o
:
$ g++ -Wall -fPIC -I. -c square.cpp
然后将square.o
链接到共享库libsquare.so
:
$ g++ -shared -o libsquare.so square.o
接下来,我们将从这些文件中创建另一个共享库libcube.so
:
cube.h
#ifndef CUBE_H
#define CUBE_H
double cube(double d);
#endif
和
cube.cpp
#include <cube.h>
#include <square.h>
double cube(double d)
{
return square(d) * d;
}
看到函数cube
调用square
,因此libcube.so
将
取决于libsquare.so
。像以前一样构建库:
$ g++ -Wall -fPIC -I. -c cube.cpp
$ g++ -shared -o libcube.so cube.o
即使libsquare
与libcube
链接也没有麻烦
取决于libcube
,尽管我们可能会这样做,因为我们正在构建libsquare
。
为此,我们无需费心将libcube
与libm
链接。默认情况下
链接器使我们可以链接包含未定义引用的共享库,并且它
非常正常。 不会让我们将程序与未定义的引用链接起来。
最后,我们使用以下库从该文件中编写一个程序:
main.cpp
libsquare
首先,将该源文件编译为#include <cube.h>
#include <iostream>
int main()
{
std::cout << cube(3) << std::endl;
return 0;
}
:
main.o
然后链接$ g++ -Wall -I. -c main.cpp
与所有三个必需的库,确保列出
链接器以依存关系顺序输入:main.o
,main.o
,libcube.so
,libsquare.so
:
libm.so
$ g++ -o prog main.o -L. -lcube -lsquare -lm
是一个系统库,因此无需告诉链接程序在哪里寻找
它。但是libm
和libcube
不是,所以我们需要告诉链接器寻找
它们放在当前目录(libsquare
)中,因为它们就在这里。 .
做到了。
我们已成功链接-L.
,但是:
./prog
它没有运行。这是因为运行时 loader 不知道在何处找到$ ./prog
./prog: error while loading shared libraries: libcube.so: cannot open shared object file: No such file or directory
(或libcube.so
,尽管距离还远)。
通常,当我们构建共享库时,我们会将它们安装在加载程序的默认库之一中
搜索目录(与链接器的默认搜索目录相同),这些目录可用于任何程序,因此不会发生。但我不是
要在我的系统上安装这些玩具库,因此,作为变通办法,我将提示装载机在哪里寻找
通过在我的shell中设置libsquare.so
为他们提供服务。
LD_LIBRARY_PATH
好。 3立方= 27。
将程序与未找到的共享库链接的另一种更好的方法
在标准系统库目录中是使用链接器的链接程序
$ export LD_LIBRARY_PATH=.
$ ./prog
27
选项。这会将一些信息写入可执行文件以告知
加载程序,它应在尝试之前在-rpath=DIR
中搜索所需的共享库
默认位置。
我们以这种方式重新链接DIR
(首先从外壳中删除./prog
,使其不再有效):
LD_LIBRARY_PATH
然后重新运行:
$ unset LD_LIBRARY_PATH
$ g++ -o prog main.o -L. -lcube -lsquare -lm -Wl,-rpath=.
要将$ ./prog
27
与g ++一起使用,请在其前面加上-rpath
,因为它是链接器-Wl
的选项,
ld
前端无法识别:g++
告诉-Wl
仅通过
选项直接进入g++
。
答案 1 :(得分:0)
在您的库中,如果您正在使用任何其他共享库,则仅您的库用户也依赖于该库。创建库时,可以使用-l,以便链接器具有共享库的概念,并且在需要时将链接。 但是,当您将库作为依赖于其他库的库交付时,也需要将其与库一起导出,并提供一些环境变量或链接器标志以从指定路径(您导出的包)中加载它。如果它的某个标准库函数用户可能会从其系统的其他库中获得定义,并且不会导致任何灾难,那将不会导致其他差异。
答案 2 :(得分:0)
就像在其他任何应用程序中一样使用该库。您不必链接到anotherclass.so
,只需链接到myclass.so
。
但是,您将必须使两个库(myclass.so
和 anotherclass.so
)都可用于以后的应用程序的运行时。如果缺少其中之一,则会像其他任何应用程序一样遇到运行时错误。
答案 3 :(得分:0)
我想在@Mike的响应中添加一些要点。
由于您没有将 libcube 库与 libsquare 链接,所以您正在创建一种“不完整的库”。当我说不完整时,我的意思是,当您链接应用程序时,您必须同时将其链接到 libcube 和 libsquare ,即使它没有直接使用 libsquare中的任何符号。
最好直接将 libcube 与 libsquare 链接。此链接将创建一个带有NEEDED条目的库,例如:
readelf -d libcube.so
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libsquare.so]
然后,当您链接应用程序时,您可以执行以下操作:
g++ -o prog main.o -L. -lcube
尽管如此,这不会链接,因为链接器试图找到需要的库 libsquare 。您必须通过在链接命令中添加 -Wl,-rpath-link =。来精确确定其路径:
g++ -o prog main.o -L. -lcube -Wl,-rpath-link=.
注意:对于运行时,您仍然必须设置 LD_LIBRARY_PATH 或链接@Mike提到的 rpath 。