-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
。这一步是头文件很重要的地方。你需要在 program.c
中进行 #include <stdlib.h>
,以便(例如)使用 malloc
和 free
。(类似地,你需要为 dlopen
和 dlsym
进行 #include <dlfcn.h>
)。如果你不这样做,编译器会抱怨它不知道这些名称是什么,并停止并报错。但如果你使用 #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。
gcc -o myprogram myprogram.c -lmysharedlib
TARGET_LINK_LIBRARIES(targetname libraryname)例如:
TARGET_LINK_LIBRARIES(myprogram mylibrary)要创建库"mylibrary",可以使用以下命令:
ADD_LIBRARY(targetname sourceslist)例如:
ADD_LIBRARY(mylibrary ${mylibrary_SRCS})此外,这种方法是跨平台的(而直接向gcc传递标志则不是)。
.so
)是存储了函数/类等实际源代码的目标文件(以二进制形式存储)。.h
)是指明编译器可以在主要代码中需要时找到所需函数/类(在.so
中)的引用文件。因此,您需要同时使用它们两个。