转自:https://www.cnblogs.com/ljtknowns/p/5647793.html
文件目录结构如下
1 dynamiclibapp.c 2 Makefile 3 comm/inc/apue.h 4 comm/errorhandle.c 5 dynamiclib/Makefile 6 dynamiclib/dynamiclib_add.c 7 dynamiclib/dynamiclib_mul.c 8 dynamiclib/inc/dynamiclibs.h 9 dynamiclib/libs/
1. dynamiclib目录
dynamiclib/inc/dynamiclibs.h 文件内容如下:
1 #ifndef __dynamic_libs_h__ 2 #define __dynamic_libs_h__ 3 4 #include "apue.h" 5 int dynamic_lib_func_add(int i1, int i2); 6 int dynamic_lib_func_mul(int i1, int i2); 7 8 #endif
dynamiclib/dynamiclib_add.c 文件内容如下:
1 #include "dynamiclibs.h" 2 3 int dynamic_lib_func_add(int i1, int i2) 4 { 5 int iret = i1 + i2; 6 printf("... in .so func, %d add %d,return %d\n", i1, i2, iret); 7 return iret; 8 }
dynamiclib/dynamiclib_mul.c 文件内容如下:
1 #include "dynamiclibs.h" 2 3 int dynamic_lib_func_mul(int i1, int i2) 4 { 5 int iret = i1 * i2; 6 printf("... in .so func, %d multiplys %d, retun %d\n", i1, i2, iret); 7 return iret; 8 }
dynamiclib/Makefile 文件内容如下:
1 CC = gcc 2 CFLAGS = -Wall -g -O -fPIC 需要加上 -fPIC 3 CXXFLAGS = 4 INCLUDE = -I ./inc -I ../comm/inc 5 TARGET = libmytest.so 6 LIBPATH = ./libs/ 7 8 vpath %.h ./inc 9 10 OBJS = dynamiclib_add.o dynamiclib_mul.o 11 SRCS = dynamiclib_add.c dynamiclib_mul.c 12 13 $(OBJS):$(SRCS) 14 $(CC) $(CFLAGS) $(INCLUDE) -c $^ 15 16 all:$(OBJS) 17 $(CC) -shared -fPIC -o $(TARGET) $(OBJS) 需要加上 -shared -fPIC 18 mv $(TARGET) $(LIBPATH) 19 20 clean: 21 rm -f *.o 22 rm -f $(LIBPATH)*
以上文件,就可以生成动态库文件 libmytest.so,应用程序以两种方式加载动态库函数,如下
2. 在编译应用程序时加载动态库
dynamiclibapp.c 文件内容如下:
1 #include "apue.h" 2 #include "dynamiclibs.h" 3 4 int main(int argc, char *argv[]) 5 { 6 err_msg("step in main\n"); 7 dynamic_lib_func_add(1, 9); 8 dynamic_lib_func_mul(1, 9); 9 err_msg("step out main\n"); 10 11 return 0; 12 }
Makefile 文件内容如下:
1 CC = gcc 2 CFLAGS = -Wall -O -g 3 CXXFLAGS = 4 INCLUDE = -I ./comm/inc -I ./dynamiclib/inc 5 TARGET = dynamiclibapp 6 LIBVAR = -lmytest 指明需要链接动态库 libmytest.so 7 LIBPATH = -L./dynamiclib/libs 指明 libmytest.so 的路径 8 #search paths for errorhandler.c 9 vpath %.c ./comm 10 #下行是为依赖项 apue.h 准备的,比如 [errorhandler.o:errorhandler.c apue.h] 里的 apue.h 11 vpath %.h ./comm/inc 12 13 OBJS = errorhandler.o dynamiclibapp.o 14 #下行的 apue.h,可以不必写出来 15 errorhandler.o:errorhandler.c apue.h 16 $(CC) $(CFLAGS) $(INCLUDE) -c $^ 17 dynamiclibapp.o:dynamiclibapp.c apue.h 18 $(CC) $(CFLAGS) $(INCLUDE) -c $^ 19 20 all:$(OBJS) $(LIB) 21 cd ./dynamiclib && make all 22 $(CC) $(CFLAGS) $(INCLUDE) -o $(TARGET) $(OBJS) $(LIBPATH) $(LIBVAR) 23 在上行中,在执行编译时,加载了 libmytest.so 中函数 24 clean: 25 rm -f *.o 26 rm -f comm/inc/*.gch 27 rm -f $(TARGET) 28 cd ./dynamiclib && make clean
对于这种方式编译出来的动态库文件,还需要在 /etc/ld.so.conf.d/ 目录中添加 libmytest.so 库文件的路径说明,
即在 /etc/ld.so.conf.d/ 目录中新建配置文件 mytest.conf,且执行 ldconfig, /etc/ld.so.conf.d/mytest.conf 的文
件内容为 libmytest.so 库文件的绝对路径,例如:
1 /home/lijiangtao/dynamiclib/libs
如果不在编译应用程序时加载动态库文件里的函数,而是改为在应用程序执行时(比如:程序的main函数启动期
间,或在程序执行期间)加载 libmytest.so 里函数,那么就可以不需在 /etc/ld.so.conf.d/ 目录中配置 libmytest.so
路径,具体如下所述。
3. 在应用程序执行时加载动态库
dynamiclibapp.c 文件内容如下:
1 #include "apue.h" 2 #include "dynamiclibs.h" 3 #include4 5 typedef int (*fp_lib_add)(int, int); 6 typedef int (*fp_lib_mul)(int, int); 7 typedef void* dlhandle; 8 9 dlhandle dll = NULL; 10 fp_lib_add func_add = NULL; 11 fp_lib_mul func_mul = NULL; 12 13 dlhandle load_dynamic_func(char *psopath, fp_lib_add *padd, fp_lib_mul *pmul); 14 15 int main(int argc, char *argv[]) 16 { 17 char *pso = "/home/lijiangtao/dynamiclib/libs/libmytest.so";//指定 .so 路径 18 dll = load_dynamic_func(pso, &func_add, &func_mul);//程序执行时,加载动态函数 19 err_msg("step in main\n"); 20 func_add(1, 9);//执行 add 函数 21 func_mul(1, 9);//执行 mul 函数 22 err_msg("step out main\n"); 23 24 return 0; 25 } 26 27 dlhandle load_dynamic_func(char *psopath, fp_lib_add *padd, fp_lib_mul *pmul) 28 { 29 if(NULL == psopath ||'\0' == psopath[0]) 30 return NULL; 31 char *perrormsg = NULL; 32 dlhandle dllhandle = dlopen(psopath, RTLD_LAZY); 33 if(NULL == dllhandle) 34 { 35 printf("%s\n", dlerror()); 36 return NULL; 37 } 38 if(NULL != padd) 39 { 40 *padd = dlsym(dllhandle, "dynamic_lib_func_add");//加载 add 函数 41 perrormsg = dlerror(); 42 if(NULL != perrormsg) 43 printf("%s\n", perrormsg); 44 } 45 if(NULL != pmul) 46 { 47 *pmul = dlsym(dllhandle, "dynamic_lib_func_mul");//加载 mul 函数 48 perrormsg = dlerror(); 49 if(NULL != perrormsg) 50 printf("%s\n", perrormsg); 51 } 52 return dllhandle; 53 }
Makefile 文件内容如下:
1 CC = gcc 2 CFLAGS = -Wall -O -g 3 CXXFLAGS = 4 INCLUDE = -I ./comm/inc -I ./dynamiclib/inc 5 TARGET = dynamiclibapp 6 LIBVAR = -ldl 需要链接 libdl.so 库 7 LIBPATH = 8 #search paths for errorhandler.c 9 vpath %.c ./comm 10 #下行是为依赖项 apue.h 准备的,比如 [errorhandler.o:errorhandler.c apue.h] 里的 apue.h 11 vpath %.h ./comm/inc 12 13 OBJS = errorhandler.o dynamiclibapp.o 14 #下行的 apue.h,可以不必写出来 15 errorhandler.o:errorhandler.c apue.h 16 $(CC) $(CFLAGS) $(INCLUDE) -c $^ 17 dynamiclibapp.o:dynamiclibapp.c apue.h 18 $(CC) $(CFLAGS) $(INCLUDE) -c $^ 19 20 all:$(OBJS) $(LIB) 21 cd ./dynamiclib && make all 22 $(CC) $(CFLAGS) -rdynamic $(INCLUDE) -o $(TARGET) $(OBJS) $(LIBPATH) $(LIBVAR) 23 在上行,执行编译时并没有加载动态接口函数,而是在应用程序执行时加载的;需要 -rdynamic 选项,
以确保 dlopen 这些接口可用 24 clean: 25 rm -f *.o 26 rm -f $(TARGET) 27 cd ./dynamiclib && make clean
对于这种方式编译出来的动态库文件,不需要在 /etc/ld.so.conf.d/ 目录中配置 libmytest.so 库文件的路径说明
多源码路径Makefile编写
CC = arm-linux-gnueabihf-gcc CXXFLAGS = INC_DIR = ./inc LIB_DIR = ./lib OBJ_DIR = ./obj PPP_DIR = ./ppp WIFI_DIR = ./wifi TARGET = $(LIB_DIR)/libhal.so CFLAGS = -Wall -O -g -fPIC -I$(INC_DIR) SRCS = $(wildcard $(PPP_DIR)/*.c $(WIFI_DIR)/*.c) OBJS = $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(SRCS))) $(TARGET):$(OBJS) $(CC) -shared -fPIC -o $@ $(OBJS) # ppp module $(OBJ_DIR)/%.o:$(PPP_DIR)/%.c $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< # wifi module $(OBJ_DIR)/%.o:$(WIFI_DIR)/%.c $(CC) $(CFLAGS) $(INCLUDE) -o $@ -c $< clean: rm -f $(OBJS) $(LIBPATH)$(TARGET)