您应该查看(并构建)一些现有的免费软件库,对其进行编译,并研究其代码和构建过程。
一般来说,一个共享对象可以由几个 C 源文件src1sh.c
和src2sh.c
......很多时候,编译是由一个构建器程序驱动的,通常是GNU make
首先,您需要将共享对象的每个源文件编译为与位置无关的代码(PIC),例如
gcc -Wall -fPIC src1sh.c -c -o src1sh.pic.o
gcc -Wall -fPIC src2sh.c -c -o src2sh.pic.o
您可能希望添加-g
到gcc
标志以进行调试。一旦你的程序和共享对象没有错误,因为你已经用gdb
和调试了它们valgrind
,传递-O2
给gcc
它们以优化它们。
然后您需要将所有这些 PIC 对象文件链接到单个共享对象(*.so
文件)中,例如
gcc -shared src1sh.pic.o src2sh.pic.o -o shared.so
如果您的意图是创建一个共享库,请调用它,lib*.so
例如libfoo.so
,并将其作为使用共享库的链接命令的-lfoo
标志。gcc
请注意,链接共享对象也可能链接其他共享库,因此您可以这样做
gcc -shared src1sh.pic.o src2sh.pic.o -lsome -o shared.so
将一些链接libsome.so
到您的shared.so
您通常不会编译包含 a 的共享对象main
(请记住,这main
是一个非常特殊的函数,在Ccrt*.o
标准中专门描述,并从链接gcc
到每个程序的启动代码中调用);这几乎是无意义的(就像你的libexample2.so
)。您main
在您的程序中定义(并且您的程序可执行文件不需要 PIC 代码)。如果您的程序由源文件制成src1pr.c
并且src2pr.c
(定义main
)您首先将它们编译为
gcc -Wall src1pr.c -c -o src1pr.o
gcc -Wall src2pr.c -c -o src2pr.o
你把它们都用例如
gcc src1pr.o src2pr.o -o prog -lshared
where-lshared
指的是一个共享库libshared.so
(您可能希望编译和链接您的程序文件以-g
获取调试信息,并且您可能希望-I
为包含目录传递其他标志,并-L
为库目录传递标志,例如-L.
在当前目录中搜索库.. .)
有一种方法可以在运行时动态链接一些共享对象,特别是对于拥有plugins。然后,您想为此使用dlopen & dlsym
functons(并且您通常希望将主程序与-rdynamic
标志链接)。
您可以(从您的程序)调用共享对象内的任何可见函数。您可能想要使用visibility
函数属性来限制共享对象内某些函数的可见性。您可能希望稍后使用该constructor
属性,以便在初始化时尽早调用共享对象内的函数(如果它是插件,则在其dlopen
时间)。
阅读Program Library Howto和Levine 的“Linkers and Loaders”一书了解更多信息。Linux 共享对象(以及可重定位对象*.o
和可执行二进制文件)采用可执行和可链接格式(ELF 是行业标准)。应用程序二进制接口(尤其是处理器的 ABI 补充,例如AMD64 ABI 补充)中描述了一些进一步的细节。
PS。你真的想要一个像 GNU make这样的构建器来组合所有这些步骤,所以请阅读它的文档。你可能想通过-v
来gcc
了解它在做什么......