UNIX环境下用C语言写静态库与动态库
静态库,动态库用UNIX 的术语来说,或者叫做归档文件(archive 常以.a 结尾)和共享对象(share object 常以lib 开头.so 结尾)更为准确。静态库,动态库可能是WINDOWS 下的术语,但两者的概念是一样的。下面统一说静态库和动态库。
静态库,就是一大堆object (CC ,CC 在LINUX 下其实是软件链接到GCC 的,编译后默认为.o 结尾的)的集合。静态库就是用ar 等工具集合在一起。在编译的时候,连接器就会将这部分代码嵌入到目标代码里。
动态库,也是一大堆object 的集合(编译成动态或静态,只是编译选项的不同)。不同的时,在编译的时候,连接器并没有将这部分代码嵌入到目标代码里,而在运行时的时候,才加载代码。
由此,一般情况下用静态库一般都比动态库大。
一、静态库编写
以简单起见,写个非常简单例子。
//hello.h
#ifndef _HELLO_H
#define _HELLO_H
void sayhello(const char* msg);
void saygoodbye(const char* msg);
#endif
//hello.c
#include "hello.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
void sayhello(const char* msg)
{
char wel[] = "welcome to invoke sayhello function/n";
char hellomsg[BUFSIZ] = "hello, ";
write(STDOUT_FILENO, wel, strlen(wel)+1);
strcat(hellomsg, msg);
strcat(hellomsg, "/n");
write(STDOUT_FILENO, hellomsg, strlen(hellomsg)+1);
}
void saygoodbye(const char* msg)
{
char wel[] = "welcome to invoke saygoodbye function/n";
char goodbyemsg[BUFSIZ] = "goodbye, ";
write(STDOUT_FILENO, wel, strlen(wel)+1);
strcat(goodbyemsg, msg);
strcat(goodbyemsg, "/n");
write(STDOUT_FILENO, goodbyemsg, strlen(goodbyemsg)+1);
}
先编译
[heidong@bogon hellolib]$ gcc -Wall -c hello.c
上面命令将产生hello.o 的obj 文件。(PS 一下:注意到bogon 了吗?你可以猜测我的网络环境)。-Wall 表示打开所有的编译警告。-c 表示只编译不连接。
再创建静态库
[heidong@bogon hellolib]$ ar -cru libhello.a hello.o
一般库文件是以lib 开头的,链接的时候不必指定lib 前缀。-cru 表示创建并替换为最新的。具体各个参数参看ar 的man 页。为了方便,抄袭一些来,鲁迅说拿来主义。
Option Name Example
-d Delete ar -d <archive> <objects>
-r Replace ar -r <archive> <objects>
-t Table list ar -t <archive>
-x Extract ar -x <archive> <objects>
-v Verbose ar -v
-c Create ar -c <archive>
-ru Update object ar -ru <archive> <objects>
至此,文件如下
[heidong@bogon hellolib]$ ls
hello.c hello.h hello.o libhello.a
测试
//statictest.c
#include "hello.h"
int main(int argc, char**argv)
{
char msg[] = "heidong";
sayhello(msg);
saygoodbye(msg);
return 0;
}
编译
[heidong@bogon hellolib]$ gcc -o statictest.o statictest.c -L. -lhello
-L. 表示将当前目录添加到库查找目录里。系统标准的库目录是/usr/lib, /lib, /usr/local/lib 等等。-lhello 表示连接libhello 这个静态库。
测试
[heidong@bogon hellolib]$ ./statictest.o
welcome to invoke sayhello function
hello, heidong
welcome to invoke saygoodbye function
goodbye, heidong
工作了。
二、动态库
代码依然是用上面的,但是编译的选项却不同。
编译
[heidong@bogon hellolib]$ gcc -c hello.c -fPIC
[heidong@bogon hellolib]$ gcc -shared hello.o -o libhello.so
[heidong@bogon hellolib]$ gcc -o statictest.o statictest.c -L. -lhello
-fPIC 表示位置独立的。具体是什么的缩写不知道。第一行生成 hello.o ,第二行将生成动态库libhello.so 。第三行的意思我上面所说的一样。
测试
[heidong@bogon hellolib]$ ./statictest.o
./statictest.o: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
咦,出错,原因就是找不到 libhello.so 这个动态库。有两个解决办法。第一,最简单的就是将库文件复制到系统库目录。需要根用户权限。第二种办法,添加 LD_LIBRARY_PATH 环境变量为所在库的目录。
再次测试
[heidong@bogon hellolib]$ export LD_LIBRARY_PATH=./
[heidong@bogon hellolib]$ ./statictest.o
welcome to invoke sayhello function
hello, heidong
welcome to invoke saygoodbye function
goodbye, heidong
Ok 啦。
可以用ldd 查看依赖于哪些库。
[heidong@bogon hellolib]$ ldd statictest.o
linux-gate.so.1 => (0x00ddf000)
libhello.so => ./libhello.so (0x00e98000)
libc.so.6 => /lib/libc.so.6 (0x00b2a000)
/lib/ld-linux.so.2 (0x00232000)
可见,除了我们的库外,还有额外三个。 libc.so.6 为标准C 的库, lib/ld-linux.so.2为动态连接/加载的库。至于第一个,不太清楚,网上说是“linux-gate.so.1 文件目前在文件系统中根本就不被支持 ; 它只是一个虚拟的DSO (译者注virtual DSO :dynamically shared object ),一个在每个进程的存储空间(process’ memory )指定的地址点被内核暴露出来的共享对象”
三、运行时加载动态库
就是在程序运行的过程中动态地加载动态库(和WINDOWS 下的LoadLibrary 一样)。四个关键的函数:
#include <dlfcn.h>
void *dlopen( const char *filename, int flag );
const char *dlerror( void );
void *dlsym( void *handle, char *symbol );
int dlclose( void *handle );
例子:
#include <unistd.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
void (*sayhello)(const char*);
void (*saygoodbye)(const char*);
void* handle = NULL;
char* err;
handle = dlopen("libhello.so", RTLD_LAZY);
if(handle == NULL){
fprintf(stderr, "%s/n", dlerror());
exit(-1);
}
sayhello = dlsym(handle, "sayhello");
err = dlerror();
if(err != NULL){
fprintf(stderr, "%s/n", err);
}else{
sayhello("heidong");
}
saygoodbye = dlsym(handle, "saygoodbye");
err = dlerror();
if(err != NULL){
fprintf(stderr, "%s/n", err);
}else{
saygoodbye("heidong");
}
saygoodbye = dlsym(handle, "sssssssaygoodbye");
err = dlerror();
if(err != NULL){
fprintf(stderr, "%s/n", err);
}else{
saygoodbye("heidong");
}
dlclose(handle);
return 0;
}
编译+测试
[heidong@bogon hellolib]$ gcc -Wall -ldl dynamicload.c -o dynamicload.out
[heidong@bogon hellolib]$ ./dynamicload.out
welcome to invoke sayhello function
hello, heidong
welcome to invoke saygoodbye function
goodbye, heidong
./libhello.so: undefined symbol: sssssssaygoodbye
[heidong@bogon hellolib]$
最后一个没有,所以出错。
四、一些常用工具
4.1 file, 测试文件类型:
[heidong@bogon hellolib]$ file libhello.so
libhello.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
[heidong@bogon hellolib]$ file statictest.o
statictest.o: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
[heidong@bogon hellolib]$
4.2 size 测试可执行文件的代码。
[heidong@bogon hellolib]$ size statictest.o
text data bss dec hex filename
1167 264 8 1439 59f statictest.o
text 为代码段,data 为已经初始化的变量,bbs 为未初始为的变量。Dec 和hex 分别为前三个之和的十进制和十六进制表示。
4.3 nm 查看有哪些导出函数。
[heidong@bogon hellolib]$ nm libhello.so | grep " T "
00000784 T _fini
00000308 T _init
000005cb T saygoodbye
0000046c T sayhello
4.4 objdump 类似windows 下的dumpbin 。
[heidong@bogon hellolib]$ objdump -d libhello.so
libhello.so: file format elf32-i386
Disassembly of section .init:
00000308 <_init>:
308: 55 push %ebp
309: 89 e5 mov %esp,%ebp
30b: 83 ec 08 sub $0x8,%esp
UNIX环境下用C语言写静态库与动态库的更多相关文章
- 在windows下用C语言写socket通讯实例
原文:在windows下用C语言写socket通讯实例 From:Microsoft Dev Center #undef UNICODE #define WIN32_LEAN_AND_MEAN #in ...
- 在 win10 环境下,设置自己写的 程序 开机自动 启动的方法
原文:在 win10 环境下,设置自己写的 程序 开机自动 启动的方法 1.是登录自己用户时才能开机启 C:\Users\username\AppData\Roaming\Microsoft\Wind ...
- C语言静态库与动态库(Windows下测试)
转载于:https://zhidao.baidu.com/question/1946953913764139388.html,原文为Linux上测试,本文为在Windows上编译测试 我们通常把一些公 ...
- Linux下Gcc生成和使用静态库和动态库详解
参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...
- Windows下静态库、动态库的创建和调用过程
静态库和动态库的使用包括两个方面,1是使用已有的库(调用过程),2是编写一个库供别人使用(创建过程).这里不讲述过多的原理,只说明如何编写,以及不正确编写时会遇见的问题. //注:本文先从简单到复杂, ...
- Linux下Gcc生成和使用静态库和动态库详解(转)
一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...
- 在Linux下如何使用GCC编译程序、简单生成 静态库及动态库
最近在编写的一个Apache kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a 静态库编译的,,,而我们这 ...
- [转]Linux下用gcc/g++生成静态库和动态库(Z)
Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10| 分类: linux | 标签:链接库 linux g++ gcc |举报|字号 订阅 ...
- linux下的共享库(动态库)和静态库
1.什么是库在windows平台和linux平台下都大量存在着库.本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于windows和linux的本质不同,因此二者库的二进制是不 ...
随机推荐
- hibernate CascadeType属性说明
CascadeType.PERSIST //只有A类新增时,会级联B对象新增.若B对象在数据库存(跟新)在则抛异常(让B变为持久态) CascadeType.MERGE //指A类新增或者变化,会级联 ...
- 第八篇 EBS实现企业日常业务运管模型的解决方案设计思路
常业务运管模型企业有大有小,各行各业,千差万别,但,其日常业务运管也有相通之处,以典型的制造企业为例,其日常业务运管模型如下图所示: (1)企业日常业务运管模型在市场经济条件下,一个生产型 ...
- URAL1091. Tmutarakan Exams(容斥)
1091 容斥原理 #include <iostream> #include<cstdio> #include<cstring> #include<algor ...
- D3D渲染流程--转载
http://www.cnblogs.com/ixnehc/articles/1282350.html 先从最基础的写起吧,关于Device的渲染流程. D3D9的Device就是D3D给我们提供的一 ...
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...
- Linux多线程(二)(线程等待,退出)
1. 线程的等待退出 1.1. 等待线程退出 线程从入口点函数自然返回,或者主动调用pthread_exit()函数,都可以让线程正常终止 线程从入口点函数自然返回时,函数返回值可以被其它线程用pth ...
- UVa 11481 (计数) Arrange the Numbers
居然没有往错排公式那去想,真是太弱了. 先在前m个数中挑出k个位置不变的数,有C(m, k)种方案,然后枚举后面n-m个位置不变的数的个数i,剩下的n-k-i个数就是错排了. 所以这里要递推一个组合数 ...
- UVa 12627 (递归 计数 找规律) Erratic Expansion
直接说几个比较明显的规律吧. k个小时以后,红气球的个数为3k. 单独观察一行: 令f(r, k)为k个小时后第r行红气球的个数. 如果r为奇数,f(r, k) = f((r+1)/2, k-1) * ...
- [转] POJ DP问题
列表一:经典题目题号:容易: 1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1191,1208, 1276, 13 ...
- HDU 5360 Hiking 登山 (优先队列,排序)
题意: 有n个人可供邀请去hiking,但是他们很有个性,每个人都有个预期的人数上下限[Li,Ri],只有当前确定会去的人数在这个区间内他才肯去.一旦他答应了,无论人数怎样变更,他都不会反悔.问最多能 ...