[动态库]动态库生成和使用以及Makefile编写
转自: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 #include <dlfcn.h>
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 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 库文件的路径说明
4. 多源码路径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)
[动态库]动态库生成和使用以及Makefile编写的更多相关文章
- linux 下C语言编程库文件处理与Makefile编写
做开发快3年了,在linux下编译安装软件算是家常便饭了.就拿gcc来说,都有不下10次了,可基本每次都会碰到些奇奇怪怪的问题.看来还是像vs.codeblocks这样的ide把人弄蠢了.便下定决心一 ...
- 生成lua的静态库.动态库.lua.exe和luac.exe
前些日子准备学习下关于lua coroutine更为强大的功能,然而发现根据lua 5.1.4版本来运行一段代码的话也会导致 "lua: attempt to yield across me ...
- c/c++:动态库 静态库 linux/windows 例子 (转)
作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). C++静 ...
- C/C++ 跨平台交叉编译、静态库/动态库编译、MinGW、Cygwin、CodeBlocks使用原理及链接参数选项
目录 . 引言 . 交叉编译 . Cygwin简介 . 静态库编译及使用 . 动态库编译及使用 . MinGW简介 . CodeBlocks简介 0. 引言 UNIX是一个注册商标,是要满足一大堆条件 ...
- Linux 下动态库 / 静态库(依赖)
一. 依赖动态库的动态库 libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而mai ...
- Ribbon2: 创建动态的Ribbon库
Sam Radakovitz曾在Excel团队博客中发表过一篇文章,介绍了如何创建动态的Ribbon库,即如何通过RibbonX和VBA放置动态的图形图像到功能区库中,在该文中,作者创建了两个库:一个 ...
- Linux 静态库&动态库调用
1.什么是库在windows平台和linux平台下都大量存在着库.本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于windows和linux的本质不同,因此二者库的二进制是不 ...
- Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明
本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1.添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此 ...
- gcc 动态编译 动态库路径
gcc 动态编译(共享库) 动态编译的可执行文件需要附带一个的动态链接库,在执行时,需要调用其对应动态链接库中的命令优点:体积小,编译快缺点:依赖性高 代码如下: [root@74-82-173-21 ...
随机推荐
- Linux共享内存使用常见陷阱与分析
所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如 信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段 ...
- vc2010 属性值无效 灾难性故障 解决方法
原文链接: http://blog.csdn.net/enterlly/article/details/8739281 说明: 我遇到这个问题是这样的,在为某个类添加消息时出现的.因为该类不在此工程的 ...
- [转]Spring mvc interceptor配置拦截器,没有登录跳到登录页
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.s ...
- UITableView 滚动到最后一行
if (self.tableView.contentSize.height > self.tableView.frame.size.height) { CGPoint offset = CGPo ...
- 手把手教你使用“谷歌云消息服务(GCM)"
原文: http://android.eoe.cn/topic/summary GCM结构概述-GCM Architectural Overview 快速预览* 一个状态通知允许应用程序通知用户一个事 ...
- 牛腩学用MUI做手机APP
斗鱼直播间直播学习撸码,最终目标是用MUI做一个手机APP(暂定android平台,攒钱买IPHONE 7SE!!!),直播内容含整个软件APP的制作过程(含后台接口的制作,放到自己买的阿里云服务器, ...
- spring(三) spring事务操作
前面一篇博文讲解了什么是AOP.学会了写AOP的实现,但是并没有实际运用起来,这一篇博文就算是对AOP技术应用的进阶把,重点是事务的处理. --wh 一.jdbcTemplate 什么是JdbcTem ...
- FullWebBrowserCookie 取得WebBrowser的完整Cookie
using System; using System.ComponentModel; using System.Net; using System.Runtime.InteropServices; u ...
- 自定义Django中间件(登录验证中间件实例)
前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰 ...
- lua笔记二 赋值语句
赋值是改变一个变量的值和改变表域的最基本的方法. a = "hello" .. "world" t.n = t.n + 1 Lua可以对多个变量同时赋值,变量列 ...