我对程序如何使用共享库有一些疑问。
当我构建一个共享库(使用 -shared -fPIC 开关)时,我会从外部程序中提供一些功能。通常我会做一个 dlopen() 来加载库,然后 dlsym() 将上述函数链接到一些函数指针。此方法不涉及包含任何 .h 文件。有没有办法避免做 dlopen() & dlsym() 并且只包括共享库的 .h ?
我 想 这可能是 c++ 程序如何使用存储在系统共享库中的代码。即只包括stdlib.h等。
原文由 nick2k3 发布,翻译遵循 CC BY-SA 4.0 许可协议
尼克,我认为所有其他答案实际上都是在回答您的问题,即您如何链接库,但是您提出问题的方式表明您对头文件和库之间的区别存在误解。他们不一样。你需要 _两者_,他们做的不是同一件事。
构建可执行文件有两个主要阶段,编译(将源代码转换为中间形式,包含可执行的二进制指令,但不是可运行的程序)和链接(将这些中间文件组合成单个运行的可执行文件或库)。
当您执行
gcc -c program.c
时,您正在编译,并生成program.o
。这一步是 标题 很重要的地方。您需要#include <stdlib.h>
在program.c
中(例如)使用malloc
和free
。 (同样,您需要#include <dlfcn.h>
用于dlopen
和dlsym
。)如果您不这样做,编译器会抱怨它不知道这些名称是什么,并因错误而停止。但是,如果您执行#include
标头,编译器 不会 将您调用的函数的代码插入program.o
。它只是插入对它们的 _引用_。原因是为了避免重复代码:程序的每个部分只需要访问一次代码,因此如果您需要更多文件(module1.c
,module2.c
和依此类推),即使他们 都 使用了malloc
您最终只会得到对malloc
的单个副本的许多引用。该单个副本以共享或静态形式(libc.so
或libc.a
)存在于标准 库 中,但您的源代码中未引用这些副本,编译器不知道它们.链接器 是.在链接阶段,您执行
gcc -o program program.o
。然后,链接器将搜索您在命令行上传递的所有库,并找到您调用的所有未在您自己的代码中定义的函数的 单一 定义。这就是-l
所做的(正如其他人所解释的那样):告诉链接器您需要使用的库列表。它们的名称通常与您在上一步中使用的标题无关。 For example to get use ofdlsym
you needlibdl.so
orlibdl.a
, so your command-line would begcc -o program program.o -ldl
.要使用malloc
或std*.h
头文件中的大多数功能,您需要libc
,但是因为 每个 C 程序都使用该库,所以它是 自动 链接的如果您已经完成了-lc
)。对不起,如果我要详细介绍,但如果你不知道你会想要的区别。如果不这样做,就很难理解 C 编译的工作原理。
最后一件事:
dlopen
和dlsym
不是正常的链接方法。它们用于特殊情况,您希望根据信息动态确定您想要的行为,无论出于何种原因,这些信息仅在运行时可用。如果您知道要在编译时调用哪些函数(在 99% 的情况下为真),则不需要使用dl*
函数。