linux 动态链接库 指定,Linux动态链接库

动态链接库是一种通用的软件组件技术,是多种操作系统中提供基本服务的方式。比如Win32内核就是3个DLL文件构成。这种技术在Linux操作系统下也有对应的实现,就是Linux标准对象Standard

Ojbect,对应的文件扩展名为.so。

下面通过一个简单的例子开始介绍Linux标准对象。

我们的标准对象文件含有一个函数,不需要声明export导出符号,只需要编译器设置即可。如下:

#include

#include

void show() {

printf("Standard Object by

gashero\n");

}

保存为myso.c文件,按照如下编译:

$ gcc -fPIC -shared -o libmyso.so myso.c

执行生成一个libmyso.so文件,按照Linux标准对象的命名惯例,应该在库名称之前加上"lib"前缀,尽管不是必须的。编译开关-fPIC代表函数符号可以重定向,-shared代表编译结果是一个标准对象。

不同于Win32DLL,Linux标准对象中的所有函数都是直接导出的,都可以被调用程序所访问。下面我们编写调用程序:

#include

int main() {

printf("Invoke my so\n");

show();

return 0;

}

保存为invoke.c,按照如下gcc开关编译:

$ gcc -o test invoke.c ./libmyso.so

编译生成test可执行文件。如上编译条件的最后一条需要是所调用的标准对象文件名,注意必须含有路径。如果只是使用libmyso.so,则必须确保这个文件在可访问的PATH下面。本例所使用的文件名"./libmyso.so"是当前路径下的,使用了相对路径。

如下测试结果:

$ ./test

Invoke my so

Standard Object by gashero

希望上文的例子可以对大家有所帮助。如何在

Linux 下调试动态链接库大家都知道在 Linux 可以用 gdb 来调试应用程序,当然前提是用 gcc 编译程序时要加上

-g

参数。

我这篇文章里将讨论一下用 gdb 来调试动态链接库的问题。

首先,假设我们准备这样的一个动态链接库:

QUOTE:

库名称是: ggg

动态链接库文件名是: libggg.so

头文件是: get.h

提供这样两个函数调用接口:

int get

();

int set (int

a);

要生成这样一个动态链接库,我们首先编写这样一个头文件:

[Copy to clipboard]

CODE:

int get ();

int set (int a);

然后准备这样一个生成动态链接库的源文件:

[Copy to clipboard]

CODE:

#include

#include "get.h"

static int x=0;

int get ()

{

printf ("get x=%d\n", x);

return x;

}

int set (int a)

{

printf ("set a=%d\n", a);

x = a;

return x;

}

然后我们用 GNU 的 C/C++ 编译器来生成动态链接库,编译命令如下:

QUOTE:

g++ get.cpp -shared -g -DDEBUG -o libggg.so

这样我们就准备好了动态链接库了,下面我们编写一个应用程序来调用此动态链接库,源代码如下:

[Copy to clipboard]

CODE:

#include

#include "get.h"

int main (int argc, char** argv)

{

int a = 100;

int b = get ();

int c = set (a);

int d = get ();

printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);

return 0;

}

编译此程序用下列命令,如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如 /lib 或

/usr/lib 之类的,就用下面这条命令:

QUOTE:

g++ pk.cpp -o app -Wall -g -lggg

否则就用下面这条命令:

QUOTE:

g++ pk.cpp -o app -Wall -g -lggg -L`pwd`

下面我们就开始调试上面命令生成的 app 程序吧。如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如

/lib或 /usr/lib 之类的,调试就顺利完成,如下

QUOTE:

linux#gdb">zhoulifa@linux#gdb ./app

GNU gdb 6.4-debian

Copyright 2005 Free Software Foundation,Inc.

GDB is free software, covered by the GNU

General Public License, and you are

welcome to change it and/or distribute

copies of it under certain conditions.

Type "show copying" to see theconditions.

There is absolutely no warranty for GDB.

Type "show warranty" for details.This GDB was configured as

"i486-linux-

gnu"...Using host libthread_db

library"/lib/tls/i686/cmov/libthread_db.so.1".

(gdb) b

main Breakpoint 1 at 0x804853c: file pk.cpp,line 7.

(gdb) b

set Function "set" not defined.

Make breakpoint pending on future shared

library load? (y or [n]) y Breakpoint 2 (set) pending.

(gdb) run

Starting program: /data/example/c/app

Breakpoint 3 at 0xb7f665f8: file get.cpp,line 11.

Pending breakpoint "set" resolved

Breakpoint 1, main (argc=1,argv=0xbf990504) at pk.cpp:7

7 int a = 100;

(gdb)

n 8 int b = get ();

(gdb)

n get x=0

9 int c = set (a);(gdb) n

Breakpoint 3, set (a=100) at get.cpp:11

11 printf ("set a=%d\n", a);

(gdb) list 6 printf ("get x=%d\n", x);

7 return x;

8 }

9 int set (int a)

10 {

11 printf ("set a=%d\n", a);

12 x = a;

13 return x;

14 }

(gdb) n

set a=100

12 x = a;(gdb) n

13 return x;(gdb) n

14 }

(gdb) n

main (argc=1, argv=0xbf990504) at

pk.cpp:10

10 int d = get ();

(gdb) n

get x=100

11 printf ("a=%d,b=%d,c=%

d,d=%d\n",a,b,c,d);

(gdb) n

a=100,b=0,c=100,d=100

12 return 0;

(gdb) c

Continuing.

Program exited normally.

(gdb) quit

如果我们没有把动态链接库放到指定目录,比如/lib里面,调试就会失败,过程如下:

QUOTE:

zhoulifa@linux# gdb ./app

GNU gdb 6.4-debian

Copyright 2005 Free Software Foundation,

Inc.

GDB is free software, covered by the GNU

General Public License, and you arewelcome to change it and/or

distribute

copies of it under certain conditions.

Type "show copying" to see theconditions.

There is absolutely no warranty for GDB.

Type "show warranty" for details.

This GDB was configured as "i486-linux-

gnu"...Using host libthread_db library

"/lib/tls/i686/cmov/libthread_db.so.1".

(gdb) b main

Breakpoint 1 at 0x804853c: file pk.cpp,

line 7.

(gdb) b set

Function "set" not defined.

Make breakpoint pending on future shared

library load? (y or [n]) y

Breakpoint 2 (set) pending.

(gdb) run Starting program: /data/example/c/app

/data/example/c/app: error while loading

shared libraries: libggg.so: cannot open

shared object file: No such file or

directory

Program exited with code 0177.

(gdb) quit

zhoulifa@linux#

本次实验的环境是:

CPU:AMD Athlon(tm) 64 Processor 3000+

内存:512M

OS:Ubuntu GNU/Linux 6.06 dapper

LTS

gcc:gcc 版本 4.0.3 (Ubuntu 4.0.3-1ubuntu5)

Linux下使用动态链接库使用动态链接库,我认为,再比较大的程序运行过程中,是一种很有优势的。所以就花了一天时间来学习一下。

使用动态链接库,需要了解一下内容

头文件:

函数:

void *dlopen(const char *filename, int flag);

const char *dlerror(void);

void *dlsym(void *handle, char *symbol);

int dlclose(void *handle);

相关的信息可以通过 man dlopen查询

在编译动生成态链接库的时候,

需要参数 -shared

在使用动态链接库的时候,

需要参数 -ldl

其他相关参数有

-fpic -fPIC -rdynamic

如有库函数文件Lib.c, 主函数文件Main.c

则有如下Makefile

all: comple

link

comple:

gcc -c Lib.c -o Lib.o

gcc -c Main.c -o Main.o

link:

gcc -shared Lib.o

-o Lib.so

gcc -ldl Main.o

-o Main

另外,在C++中使用动态连接库的时候,请注意:

必须用

extern "C"

{

}

将动态苦定义为C的编译连接方式

否则由于C++命名方式于C不同,会造成生成的动态链接库不能使用(无法定位或函数)

文章选取的例子非常简单,上手容易,只是为了讲述静态与动态链接库的生成和链接过

程,还有他们之间的区别。以下例子在 gcc 4.1.1 下顺利通过。

文件预览 (补充)

文件目录树如下,如你所见,非常简单。

libtest/

|-- lt.c

|-- lt.h

`-- test.c

代码

#lt.c

#include 

voidmyprint(void)

{

printf("Linux library test!\n");

}

# lt.h

voidmyprint(void);

#test.c

#include "lt.h"

intmain(void)

{

myprint();

return0;

}

先看静态库

首先做成静态库 liblt.a 。

$ gcc -c lt.c -o lt.o

$ ar cqs liblt.a lt.o

再者,链接,这里指定了静态库的位置,注意文件顺序不可乱序。

$ gcc test.o

liblt.a -o test

这个时候再来看他的引用库情况。

$ ldd test

linux-gate.so.1 => (0xffffe000)

libc.so.6 => /lib/libc.so.6 (0xb7e29000)

/lib/ld-linux.so.2 (0xb7f6e000)

动态库

做成动态库 liblt.so 。

$ gcc -c lt.c -o lt.o

$ gcc -shared -Wall -fPIC lt.o -o liblt.so

链接方法I,拷贝到系统库里再链接,让gcc自己查找

$ sudo cp

liblt.so /usr/lib

$ gcc -o test test.o -llt

这里我们可以看到了 -llt 选项,-l[lib_name] 指定库名,他会主动搜索

lib[lib_name].so 。这个搜索的路径可以通过 gcc --print-search-dirs来查找。

链接方法II,手动指定库路径

$ cc -o test test.o -llt -B /path/to/lib

这里的-B 选项就添加 /path/to/lib 到gcc搜索的路径之中。这样链接没有问题但是方法II

中手动链接好的程序在执行时候仍旧需要指定库路径(链接和执行是分开的)。需要添加系

统变量 LD_LIBRARY_PATH :

$ export LD_LIBRARY_PATH=/path/to/lib

这个时候再来检测一下test程序的库链接状况(方法I情况)

$ ldd test

linux-gate.so.1 => (0xffffe000)

liblt.so => /usr/lib/liblt.so (0xb7f58000)

libc.so.6 => /lib/libc.so.6 (0xb7e28000)

/lib/ld-linux.so.2 (0xb7f6f000)

恩,是不是比静态链接的程序多了一个 liblt.so ?恩,这就是静态与动态的最大区别,静

态情况下,他把库直接加载到程序里,而在动态链接的时候,他只是保留接口,将动态库与

程序代码独立。这样就可以提高代码的可复用度,和降低程序的耦合度。

参考:http://www-128.ibm.com/developerworks/cn/linux/sdk/dll/index.html

http://www.oklinux.cn/html/developer/java/20070630/33743.html

http://blog.csdn.net/wenxy1/archive/2005/12/15/553216.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值