我对如何做程序使用共享库的一些疑问。
当我建立一个共享库(具有-shared -fPIC开关)我使可从一个外部程序的一些功能。 通常我做的dlopen()来加载库,然后对dlsym(),以上述的功能链接到一些函数指针。 这种方法不涉及包括任何.h文件中。 有没有办法避免这样做的dlopen()的dlsym(),只是包括共享库的.H?
我想这可能是C ++程序如何使用存储在系统中的共享库代码。 即只包括文件stdlib.h等。
我对如何做程序使用共享库的一些疑问。
当我建立一个共享库(具有-shared -fPIC开关)我使可从一个外部程序的一些功能。 通常我做的dlopen()来加载库,然后对dlsym(),以上述的功能链接到一些函数指针。 这种方法不涉及包括任何.h文件中。 有没有办法避免这样做的dlopen()的dlsym(),只是包括共享库的.H?
我想这可能是C ++程序如何使用存储在系统中的共享库代码。 即只包括文件stdlib.h等。
尼克,我认为所有的其他的答案实际上是回答你的问题,这是你如何链接库,但你那句你的问题的方式暗示你有头文件和库之间的差异的误解。 他们不一样。 你既需要,和他们没有做同样的事情。
生成可执行具有两个主要阶段,编译(其将您的源成中间形式,包含可执行二进制指令,但并不是一个可运行程序),和连接(结合了这些中间文件转换成单个运行可执行文件或库)。
当你这样做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
做(因为其他人解释):告诉链接你需要使用库列表。 他们的名字往往很少与你在上一步中使用的头。 例如,要获得使用dlsym
需要libdl.so
或libdl.a
,所以你的命令行会gcc -o program program.o -ldl
。 要使用malloc
或大部分功能std*.h
头你需要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不是)。