文件目录结构如下
dynamiclibapp.c Makefile comm/inc/apue.h comm/errorhandle.c dynamiclib/Makefile dynamiclib/dynamiclib_add.c dynamiclib/dynamiclib_mul.c dynamiclib/inc/dynamiclibs.h dynamiclib/libs/
dynamiclib目录
dynamiclib/inc/dynamiclibs.h 文件内容如下:
#ifndef __dynamic_libs_h__ #define __dynamic_libs_h__ #include "apue.h" int dynamic_lib_func_add(int i1, int i2); int dynamic_lib_func_mul(int i1, int i2); #endif
dynamiclib/dynamiclib_add.c 文件内容如下:
#include "dynamiclibs.h"
int dynamic_lib_func_add(int i1, int i2)
{
int iret = i1 + i2;
printf("... in .so func, %d add %d,return %dn", i1, i2, iret);
return iret;
}
复制代码
dynamiclib/dynamiclib_mul.c 文件内容如下:
#include "dynamiclibs.h"
int dynamic_lib_func_mul(int i1, int i2)
{
int iret = i1 * i2;
printf("... in .so func, %d multiplys %d, retun %dn", i1, i2, iret);
return iret;
}
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
(
O
B
J
S
)
:
(OBJS):
(OBJS):(SRCS)
14 $(CC) $(CFLAGS) $(INCLUDE) -c
1
516
a
l
l
:
^ 15 16 all:
1516all:(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,应用程序以两种方式加载动态库函数,如下
-
在编译应用程序时加载动态库
dynamiclibapp.c 文件内容如下:
1 #include “apue.h”
2 #include “dynamiclibs.h”
3
4 int main(int argc, char *argv[])
5 {
6 err_msg(“step in mainn”);
7 dynamic_lib_func_add(1, 9);
8 dynamic_lib_func_mul(1, 9);
9 err_msg(“step out mainn”);
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
1
920
a
l
l
:
^ 19 20 all:
1920all:(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 路径,具体如下所述。
-
在应用程序执行时加载动态库
dynamiclibapp.c 文件内容如下:
1 #include “apue.h”
2 #include “dynamiclibs.h”
3 #include
4
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 mainn”);
20 func_add(1, 9);//执行 add 函数
21 func_mul(1, 9);//执行 mul 函数
22 err_msg(“step out mainn”);
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 ||’ ’ == psopath[0])
30 return NULL;
31 char *perrormsg = NULL;
32 dlhandle dllhandle = dlopen(psopath, RTLD_LAZY);
33 if(NULL == dllhandle)
34 {
35 printf("%sn", 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("%sn", 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("%sn", 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
1
920
a
l
l
:
^ 19 20 all:
1920all:(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 库文件的路径说明



