Chinaunix首页 | 论坛 | 博客
  • 博客访问: 148891
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 908
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-03 11:03
个人简介

学习linux

文章分类
文章存档

2014年(7)

2013年(33)

我的朋友

分类: LINUX

2013-10-22 11:13:07

LINUX下C语言库的使用
1.库分类
1.1 静态库
表态库的代码编译时链接到应用程序中, 因此编译是表态库文件必须存在并且用'-l'参数传递给编译器.程序执行过程中就不再需要静态库了.

1.2 动态库
也称为共享库, 其代码不会链接到应用程序目标文件中. 程序执行过程中动态加载库文件调用里面的函数.分为隐式调用和显式调用
1) 隐式调用: 又称静态加载, 动态库会在应用程序开始执行时自动载入内存,进程结束时自动卸载。
2)显示调用: 双称动态加载, 编译时可以不显示提供动态库的路径, 但要用dlopen等函数实现调用,可以在程序中任意载入或释放动态库。

2.表态库编程

2.1 表态库的生成
可分为三个步骤: 编写源文件(*.c) -> 编译生成.o文件 -> 使用 'ar' 命令生成库文件.
下面写个例子说明:

a.首先写一个源文件 pr1.c:
#include

void print1()
{
    printf("This is the first lib src!\n");
}

b. 然后编译生成.o文件:
gcc -O -c pr1.c
ls查看一下, 已经有了一个pr1.o文件.

c.用'ar'工具生成表态库,为了编译程序时能正确找到库文件,表态库必须按照lib[name].a的规则命名.
ar -rvs libpr.a pr1.o

OK! ls查看一下, 已经有了个表态库文件libpr.a

2.2 表态库的应用

写一个测试函数(test.c)调用libpr.a里的函数:
int main()
{
    print1();//调用libpr.a里的print1()函数.
}

编译文件,用'-l'选项将静态库libpr.a的路径传给编译器.
gcc -O -o test test.c -L./ -lpr
或者:
gcc -O -o test test.c ./libpr.a
其中'-lpr'就是要链接静态库libpr.a(命名规则:lib[name].a),'-L.'/是指在当前目录下查找库文件.

现在执行目标文件:
./test
This is the first lib src!
OK!very easy~~~
符上静态库的操作命令'ar'的几个参数说明:
调用格式: ar [drqtpmx] [options] archivefile objfile ......
-r    将objfile文件插入静态库尾或替换静态库中同名文件.
-x    从静态库文件中抽取文件objfile.
-t    打印静态成员文件列表.
-d    从静态库中删除文件objfile.
-s    重置静态库文件索引.
-v    创建文件冗余信息.
-c    创建静态库文件.

3.动态库的生成
分为三个步骤: 编写源文件(.c) -> 编译生成位置无关码型.o文件(PIC) -> 链接生成动态库.
下面定个例子说明:

a) 编写源代码
... ... 这里就省事了, 就用刚写的那个pr1.c文件.

b) 使用gcc的'-fpic' 选项生成PIC中间文件
gcc -fpic -c pr1.c

c) 使用gcc的'-shared' 选项生成创建动态库文件pr1.so文件
gcc -shared -o pr1.so pr1.o

或者也可以一步到位:
gcc -O -fpic -shared -o pr1.so pr1.c

4.动态库的应用

4.1 动态库的隐式调用. 与静态库的调用接近:
编写调用动态库函数的代码, ~~~ 这里继续使用刚才的test.c
编译时,直接将动态库的路径作为参数传到编译器:
gcc -O -o test test.c ./pr1.so
执行目标文件: ./test
This is the first lib src!

OK!成功了.

4.2 动态库的显式调用
显式调用编译时无需库文件, 库文件可以在任意位置.是用系统库函数还操作动态库的.

a) 打开动态库
#include
void *dlopen(const char *pathname, int mode);
函数dlopen 加载动态库,成功返回指向动态库的指针,否则返回NULL.
pathname:    动态库路径.
mode:        加载方式: RTLD_ALZY(对象符号在被调用时解析),RTLD_NOW(所有符号在函数dlopen返回前解析)

b) 获取动态库对象地址
#include
void *dlsym(void *handle, const char *name);
函数dlsym在动态库中搜索与字符串name同名的对象(包括函数和全局变量等),成功返回对象地址,否则返回NULL.
handle:    同函数dlopen返回成功的动态库句柄.
name:    动态库对象名称.

c) 错误检查
#include
char * dlerror(void);
函数dlerror返回最近的显式操作动态库的错误信息, 无错误时返回NULL.本函数执行后会将错误信息重置为NULL.

d) 关闭动态库
#include
int dlclose(void *handle);
关闭handle指向的动态库.

下面写一个测试函数实践一下(test.c):

#include
#include

int main()
{
    void *pHandle;        //指向动态库的指针
    void (*pFunc)();    //指向函数的指针
    pHandle = dlopen("dll/pr1.so",RTLD_NOW);    //打开动态库
    if(!pHandle){
        printf("Can't find pr1.so");
        return;
    }
    pFunc = (void (*)())dlsym(pHandle, "print1");
    if(!pFunc){
        printf("Can't find func printf\n");
        return;
    }
    pFunc();

    dlclose(pHandle);    //关闭动态库
}

编译:
cp pr1.so dll/
gcc -O -o test test.c
./ test
This is first dll src!

OK! 成功了。

上面的例子都是经我测试通过的。
动态调用动态库那那几个函数在ubuntu上面编译不通过,
报错信息是: undefined reference to `dlopen'
不知道还得装哪个库, 希望有高手指点一下
阅读(1520) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~