赞
踩
- /*func.c*/
-
- #include "stdio.h"
-
- int func(void)
- {
- printf("func\n");
- return 0;
- }
-fPIC(Position Independent Code) 编译生成代码与位置无关
gcc -fPIC -c func.c -o func.o
-shared 链接一个共享库so
gcc -shared func.o -o libfunc.so
- /*main.c*/
-
- void func(void);
-
- void main(void)
- {
- func();
- }
-L: 指定so文件所在的目录。
-l:动态链接库名(即:文件名去除前缀lib,去除后缀.so)。
gcc -o main main.c -L. -lfunc
gcc -o main main.c libfunc.so
- /*dl_main.c*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dlfcn.h>
-
- typedef void (*func)(void);
-
- void main(void)
- {
- void *dl_handle;
- func func = NULL;
-
- dl_handle=dlopen("./libfunc.so",RTLD_LAZY);
- if(NULL == dl_handle)
- {
- fprintf(stderr,"%s\n",dlerror());
- exit(-1);
- }
-
- func = dlsym(dl_handle,"func");
- func();
- dlclose(dl_handle);
- return;
- }
-rdynamic 链接选项,指示链接器把所有符号都添加到动态符号表(即.dynsym表)里,以便那些通过dlopen()或backtrace()的函数使用。
gcc -rdynamic -o dl_main dl_main.c -ldl
- .SUFFIXES:.c .o
- CC=gcc
- SRCS=func.c main.c
- INCLUDE=
- LDFLAGS=
- OBJS=$(SRCS:.c=.o)
- EXEC=main
- DLL=libfunc
-
- all:$(DLL) $(EXEC)
-
- libfunc:func.o
- $(CC) -shared -o libfunc.so func.o $(LDFLAGS) -std=gnu99
-
- main:main.o
- $(CC) -g -o main main.o libfunc.so $(LDFLAGS) -std=gnu99
-
- .c.o:
- $(CC) -Wall -g -fPIC -o $(@) $(INCLUDE) -c $< -std=gnu99
- clean:
- rm -f $(OBJS) libfunc.so main
- rm -f *.o
关于 gcc/g++编译选项: -fPIC 功能的解释_yyps的博客-CSDN博客
动态库基本原理和使用方法,-fPIC选项的来龙去脉_动态库的原理_learnrocks100的博客-CSDN博客
linux 动态链接库(.so)的生成和引用_linux链接动态库so文件_进击的铁甲小宝的博客-CSDN博客
linux编译时动态链接.so文件_linux把两个so链接_搬砖工13的博客-CSDN博客
Linux 动态链接库(.so)的使用 - 旭东的博客 - 博客园 (cnblogs.com)
Linux-(C/C++)动态链接库生成以及使用(libxxx.so) (taodudu.cc)
动态链接库(Dynamic Link Library,DLL)在Windows操作系统中很常见,而在类Unix系统(包括Linux和macOS)中,这些动态链接库通常是以`.so`(共享对象,Shared Object)文件出现。`.so`文件被用作包含可以被多个程序同时使用的代码和数据的共享库。
当一个程序运行时,它会使用动态链接(相对于静态链接,静态链接是在程序编译时就固定好的)来调用需要的`.so`文件中的函数或者资源。使用动态链接库有几个好处:
1. **资源共享**:不同的程序可以共享内存中的同一份库代码,减少了系统的内存占用。
2. **模块更新**:开发者可以更新动态链接库而无需重新编译使用这些库的每一个程序。
3. **节省空间**:多个应用共享同样的库而不需要在每个应用的安装目录下都有一个副本。
一个`.so`文件可以是一个程序的核心组件,也可以提供特定功能(比如音频处理、图像处理或网络通信)供其他程序调用。在Linux系统中,安装新软件时,通常也会安装所需的`.so`库文件。如果系统中缺少所需的`.so`文件,程序可能无法启动或者运行。在运行时,系统的动态链接器负责寻找和加载所有必需的`.so`文件。
生成动态链接库的 .so 文件在 Linux 系统下一般使用 gcc 或 g++ 编译器,具体步骤如下:
1. **编写源代码**:首先,你需要有一段 C 或 C++ 编写的源代码。这段代码通常包括想要在库中共享的函数。
2. **编译源代码为目标文件**:使用编译器将源代码编译成中间的目标文件 .o,同时使用 -fPIC 标志来确保位置无关码(Position-Independent Code,PIC)的生成。这个标志是因为共享库需要能够在内存的任何位置运行。
gcc -c -fPIC source_file.c -o output_file.o
3. **创建共享对象 .so 文件**:使用生成的目标文件(`.o` 文件)来创建共享库。在这个步骤中,你会使用 -shared 标志来告诉编译器生成一个共享对象文件。
gcc -shared -o libshared.so output_file.o
如果有多个源文件,就需要将它们各自编译为 .o 文件,然后一起链接为一个 .so 文件。
4. **安装和使用共享库**:一旦共享库被创建,你可以将它安装到系统库路径中,比如 /usr/lib/ 或 /usr/local/lib/,或者任何由动态链接器支持的路径。
- 你可能需要更新动态链接器运行时绑定的缓存,使用命令 ldconfig。
- 通过设置环境变量 LD_LIBRARY_PATH,你可以让动态链接器在其他位置寻找共享库。
5. **链接共享库**:其他程序在编译时可以链接这个共享库,使用 -l 选项指定库的名称,如果库文件没有在标准路径中,还需要使用 -L 来添加库所在的目录。
gcc -o program program.c -L/path/to/library -lshared
在实际操作中,你可能还需要添加其它编译器选项来指定头文件路径(使用 -I 选项),定义宏,优化代码等。记得在创建库名称时,前缀 lib 是约定俗成的规范,而且链接时 -l 选项会自动在给定的库名前加上这个前缀去搜索符合的库文件。
动态链接库(Dynamic Link Libraries),在 Windows 操作系统中通常以 .dll 为文件后缀名,在类 Unix 系统如 Linux 上,动态链接库通常以 .so (共享对象,shared object)为后缀。动态链接库包含可以被多个程序共享的代码和数据,它们的一个主要优势是代码重用和内存节省。
以下是使用动态链接库的几个方面:
1. **创建动态链接库:**
- 在 Windows 系统中,你可以使用 C/C++ 等编程语言结合 Microsoft Visual Studio 来创建 DLL。
- 在类 Unix 系统中,你可以使用 C/C++ 等编程语言结合 GCC/G++ 编译器来创建 SO 文件。
2. **编译时指定动态链接库:**
- 开发者在编译应用程序时,可以指定链接器使用特定的动态链接库。
3. **运行时加载动态链接库:**
- 可以在程序运行时动态加载库文件,Windows 使用 LoadLibrary API,而类 Unix 系统使用 dlopen 函数,并通过 GetProcAddress (Windows) 或 dlsym (类 Unix) 来获取库中函数或变量的地址。
4. **共享代码:**
- 动态链接库允许程序在运行时共享代码和资源,这减少了程序的总体内存占用,因为库代码不需要在每个使用它的程序的地址空间中重复。
5. **依赖管理:**
- 应用程序可能依赖多个动态链接库,操作系统负责解析这些依赖,以确保库在程序运行时可用。
6. **版本控制:**
- 可以为动态链接库提供版本信息,允许同时存在多个版本的库,并让应用程序选择合适的版本。
7. **部署和更新:**
- 更新动态链接库比静态链接库更简单,因为只需替换旧的库文件即可,而不需要重新编译整个应用程序。
要在应用程序中使用动态链接库,你需要确保动态链接库在应用程序搜索库的路径上,或者将其放在系统指定的库目录中(例如 Windows 的 System32,Linux 的 /usr/lib 等)。另外,当你分发或部署使用动态链接库的应用程序时,依赖的动态链接库也需要被正确地包含在安装包中或者已经预装在目标系统上。在Unix-like系统中,如Linux和macOS,`.so` 文件代表“共享对象”(Shared Object),这与Windows中的动态链接库(DLL,Dynamic Link Library)文件相对应。动态链接库是程序运行时动态加载的外部代码库,可以同时被多个程序使用。使用`.so`文件可以避免重复代码,节省磁盘空间,并允许程序在不重新编译整个程序的情况下更新特定的功能。
下面是一般在Linux系统中使用共享对象的步骤:
1. **编译共享对象**:
你需要使用编译器(通常是gcc或g++)编译源代码,并生成`.so`文件。编译时需要指定`-fPIC`(位置无关代码)选项,以及`-shared`来生成共享对象。
例如:
gcc -fPIC -shared -o libexample.so example.c
2. **安装共享库**:
编译完成后,将`.so`文件拷贝到合适的库目录,如`/usr/local/lib`,并可能需要更新库缓存:
- sudo cp libexample.so /usr/local/lib
- sudo ldconfig
3. **链接共享库**:
当你编译一个程序,并且想要链接到这个共享库时,可以使用`-l`(指定库名)和`-L`(指定库文件目录)选项来指定链接器设置。
gcc -o myprogram myprogram.c -L/usr/local/lib -lexample
4. **动态加载共享库**:
程序也可以在运行时使用动态加载函数(如`dlopen`,`dlsym`)直接加载和使用共享库中的函数。
5. **设定环境变量**:
如果共享库不在标准库目录中,可能需要设置`LD_LIBRARY_PATH`环境变量,以告知系统在哪里查找这些库。
export LD_LIBRARY_PATH=/path/to/your/library:$LD_LIBRARY_PATH
6. **运行程序**:
在程序运行时,加载器(`ld.so`或`ld-linux.so`)将解析程序所需的所有共享库,并加载它们,使得程序能够运行。
请注意,以上步骤是在命令行环境中的操作,在使用不同的编程环境或IDE时,具体的操作可能会有所不同。此外,创建动态链接库时应确保其接口(ABI,Application Binary Interface)设计得当,以确保与使用它的程序兼容。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。