共享库和.h文件
我对程序如何使用共享库有一些疑问。
当我构建一个共享库(使用-shared -fPIC开关)时,我可以从外部程序中获取一些函数。 通常我会使用dlopen()来加载库,然后使用dlsym()将所述函数链接到某些函数指针。 此方法不涉及任何.h文件。 有没有办法避免做dlopen()和dlsym(),只包括共享库的.h?
我想这可能是c ++程序如何使用存储在系统共享库中的代码。 即仅包括stdlib.h等
尼克,我认为所有其他答案实际上都在回答你的问题,这就是你如何链接库,但是你的问题表明你对头文件和库之间的区别有误解。 他们不一样。 你需要两者 ,他们没有做同样的事情。
构建可执行文件有两个主要阶段,编译(将源转换为中间forms,包含可执行二进制指令,但不是可运行程序)和链接(将这些中间文件组合成单个运行的可执行文件或库)。
当您执行gcc -c program.c
,您正在编译,并生成program.o
。 这一步是标题很重要的地方。 你需要在program.c
#include
来(例如)使用malloc
和free
。 (类似地,对于dlopen
和dlsym
你需要#include
。)如果你不这样做,编译器会抱怨它不知道这些名字是什么,并且因错误而停止。 但是,如果您执行#include
标头,则编译器不会将您调用的函数的代码插入到program.o
。 它只是插入一个引用 。 原因是避免重复代码:代码只需要程序的每个部分都需要访问一次,所以如果你需要更多的文件( module1.c
, module2.c
等),即使它们都是使用malloc
你最终会得到许多对malloc
的单个副本的引用。 该单个副本以共享或静态forms( libc.so
或libc.a
)存在于标准库中,但这些libc.a
未在源中引用,并且编译器不知道它们。
链接器是 。 在链接阶段,你做gcc -o program program.o
。 然后链接器将在命令行中搜索您传递它的所有库,并找到您调用的所有函数的单一定义,这些函数未在您自己的代码中定义。 这就是-l
所做的(正如其他人所解释的那样):告诉链接器你需要使用的库列表。 它们的名称通常与您在上一步中使用的标题几乎没有关系。 例如,要使用dlsym
您需要libdl.so
或libdl.a
,因此您的命令行将是gcc -o program program.o -ldl
。 要在std*.h
头文件中使用malloc
或大多数函数,您需要libc
,但由于每个 C程序都使用该库,因此它会自动链接(就像您已经完成了-lc
)。
对不起,如果我进入很多细节,但如果你不知道你想要的差异。 如果不这样做,很难理解C编译的工作原理。
最后一件事: dlopen
和dlsym
不是正常的链接方法。 它们用于特殊情况,您希望根据无论何种原因仅在运行时可用的信息动态确定所需的行为。 如果您知道在编译时要调用哪些函数(在99%的情况下都是如此),则不需要使用dl*
函数。
您可以链接共享库,例如静态库。 然后在启动程序时搜索它们。 事实上,默认情况下-lXXX更喜欢libXXX.so到libXXX.a。
您需要为链接器提供链接共享库的正确指令。
共享库名称类似于libNAME.so,因此对于链接,您应该使用-lNAME
将其命名为libmysharedlib.so,然后将您的主程序链接为:
gcc -o myprogram myprogram.c -lmysharedlib
如果您使用CMake构建项目,则可以使用
TARGET_LINK_LIBRARIES(targetname libraryname)
如:
TARGET_LINK_LIBRARIES(myprogram mylibrary)
要创建库“mylibrary”,您可以使用
ADD_LIBRARY(targetname sourceslist)
如:
ADD_LIBRARY(mylibrary $ {mylibrary_SRCS})
另外,这种方法是跨平台的(而不是简单地将标志传递给gcc)。