免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2176 | 回复: 0
打印 上一主题 下一主题

LINUX DLL [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-14 17:53 |只看该作者 |倒序浏览
这份文档来自>,解释如何动态加载共享库,使用这
种技术你可以在程序中精确控制加载某个共享库。本文同时讨论了共享库中符号解析
问题。
dlopen( "libtest.so", RTLD_LAZY );
这个调用将打开共享库libtest.so,第二形参通常都是RTLD_LAZY。为了使用dlopen
函数,需要包含头文件,指定链接开关-ldl。
假设libtest.so中定义了函数my_function
--------------------------------------------------------------------------
void   *handle;
void ( *test ) ( void );
handle = dlopen( "libtest.so", RTLD_LAZY );
test   = dlsym( handle, "my_function" );
test();
dlclose( handle );
--------------------------------------------------------------------------
dlsym()系统调用还可用于获取指向共享库中某个静态变量的指针。dlopen与dlsym调
用失败时均返回NULL,此时可以调用dlerror(没有形参)获取相应的可读错误信息。
dlclose函数用于卸载共享库。技术上,dlopen只在一个共享库尚未被加载的情况下
真正加载它。如果一个共享库已经被加载了,dlopen简单地递增该共享库引用计数。
类似的,dlclose递减共享库引用计数,当引用计数达到零时卸载共享库。
如果你是用C++编写共享库,而又想用dlsym访问其中的函数、静态变量,可能需要这
样定义:
--------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"
{
#endif
static char my_char;
static void my_funtion ( void );
#ifdef __cplusplus
}
#endif
--------------------------------------------------------------------------
这使得C++编译器保持my_char、my_funtion的原始名字。对于C编译器不存在该问题。
一个共享库可能会引用外部定义的函数和变量。假设你用dlopen打开这样一个共享库。
如果指定了RTLD_LAZY,Linux不会在立即解析未定义的符号名,直到共享库中代码第
一次试图引用未定义的符号名,Linux才开始解析它。如果解析成功,程序继续执行,
反之显示错误信息并终止程序。如果指定了RTLD_NOW,Linux会在调用dlopen时立即
解析未定义的符号名。解析失败时dlopen返回NULL。
那么Linux根据什么解析未定义的符号名呢,有这么几种情况:
如果主程序引出(exports)任意动态符号(共享库正是这样做的),则这些符号自然可
用。然而缺省情况下,常规可执行程序不会以动态符号形式引出它们的函数和变量名。
为了达到这个效果,可以在编译时指定"-Wl,-export-dynamic",这实际是链接选项。
如果主程序编译时选择了动态链接,则dlopen打开的库可以引用编译时共享库中的符
号。
如果主程序使用dlopen打开共享库A、B,缺省情况下A与B彼此不能引用对方定义的动
态符号。但是可以在dlopen第二形参上逻辑或一个RTLD_GLOBAL标志,使得相应共享
库中动态符号全局可见。
--------------------------------------------------------------------------
#include
#include
#include
#include
int main ( int argc, char * argv[] )
{
    void   *handle;
    void ( *foo ) ( void );
    handle = dlopen( "libfoo.so", RTLD_LAZY );
    foo    = dlsym( handle, "foo" );
    foo();
    dlclose( handle );
    return( EXIT_SUCCESS );
}  /* end of main */
--------------------------------------------------------------------------
假设foo()调用了另一个函数bar(),而bar()不是libfoo.so中定义的,怎么办。
一种办法是在你的主程序里包含bar()函数体,然后指定"-Wl,-export-dynamic"编译
主程序:
$ cc -Wl,-export-dynamic -o main main.c bar.c -ldl
第二种办法是将bar()放到单独一个共享库里,编译时动态链接进主程序
$ cc -fPIC -shared -o libbar.so bar.c
$ cc -o main main.c libbar.so -ldl
第三种办法是将bar()放到单独一个共享库里,运行时由main函数调用dlopen动态加
载。注意,dlopen的第二形参中必须逻辑或RTLD_GLOBAL标志,否则libfoo.so看不到
libbar.so引出的动态符号。
--------------------------------------------------------------------------
void *bar_handle;
bar_handle = dlopen( "libbar.so", RTLD_LAZY | RTLD_GLOBAL );
--------------------------------------------------------------------------
Q: 我试图用dlopen()打开一个共享库,该共享库使用了一个extern型变量,后者位
   于主调二进制文件中。但是这个dlopen()调用失败了,报告存在无法解析的外部
   符号。我用的是gcc(Cygnus version 2.9),怎么解决这个问题。
--------------------------------------------------------------------------
/*
* Library testlib.c
* gcc -Wall -pipe -O3 -o testlib.o -c testlib.c
* /usr/ccs/bin/ld -G testlib.o -o testlib.so
*/
extern int abc;
void testing ( void )
{
    abc = 0;
    return;
}
/*
* Main testcall.c
* gcc -Wall -pipe -O3 -o testcall testcall.c -ldl
*/
#include
#include
#include
#include
#include
int abc = -1;
int main ( void )
{
    void *testlib;
    void ( *testing_call ) ();
    fprintf( stderr, "abc = %d\n", abc );
    if ( ( testlib = dlopen( "./testlib.so", RTLD_NOW | RTLD_GLOBAL ) ) != NULL )
    {
        testing_call = dlsym( testlib, "testing" );
        ( *testing_call )();
        fprintf( stderr, "abc = %d\n", abc );
    }
    return( EXIT_SUCCESS );
}
--------------------------------------------------------------------------
A: flyriver 2001-12-16 22:48
Linux系统中编译主调程序时加上"-rdynamic"参数
Q: 在libfoo.so中实现了func1()、func2(),其中func2()调用了func1()。主调程序
   prog.c中包含一个同名函数func1(),但与libfoo.so中func1()有不同形参类型。
   prog.c使用dlopen()打开libfoo.so,并调用其中的func2()。我期望此时func2()
   仍去调用libfoo.so中的func1(),但现在事实是调用了prog.c中的func1(),怎么
   办。
A: Paul Pluzhnikov  2003年5月31日 13:05
对于Win32、AIX来说,你所期待的效果是缺省行为,但其它操作系统未必如此。对于
Solaris、FreeBSD、Linux,使用gnu ld生成libfoo.so时应指定-Bsymbolic。缺省情
况下没有指定-Bsymbolic,此时prog.c中的func1()被func2()调用。
A: Mars Rullgard  2003年5月30日 17:09
如果libfoo.so没有使用prog.c中符号(变量、函数),使用gnu ld链接prog.c时不要
指定-rdynamic或者-export-dynamic,这样prog.c中func1符号不被引出,func2()就
不会调用func1()。如果还是不能解决问题,设法使func1这个符号成为weak symbol,
假设你正在使用gcc,可以这样做:
int __attribute__((weak)) func1 ( ... )
{
    ... ...
}

Q: 我试图用dlopen()打开一个共享库,该共享库使用了一个extern型变量,后者位
   于主调二进制文件中。但是这个dlopen()调用失败了,报告存在无法解析的外部
   符号。我用的是gcc(Cygnus version 2.9),怎么解决这个问题。
--------------------------------------------------------------------------
/*
* Library testlib.c
* gcc -Wall -pipe -O3 -o testlib.o -c testlib.c
* /usr/ccs/bin/ld -G testlib.o -o testlib.so
*/
extern int abc;
void testing ( void )
{
    abc = 0;
    return;
}
/*
* Main testcall.c
* gcc -Wall -pipe -O3 -o testcall testcall.c -ldl
*/
#include
#include
#include
#include
#include
int abc = -1;
int main ( void )
{
    void *testlib;
    void ( *testing_call ) ();
    fprintf( stderr, "abc = %d\n", abc );
    if ( ( testlib = dlopen( "./testlib.so", RTLD_NOW | RTLD_GLOBAL ) ) != NULL )
    {
        testing_call = dlsym( testlib, "testing" );
        ( *testing_call )();
        fprintf( stderr, "abc = %d\n", abc );
    }
    return( EXIT_SUCCESS );
}
--------------------------------------------------------------------------
A: flyriver 2001-12-16 22:48
Linux系统中编译主调程序时加上"-rdynamic"参数
其实这个例子在 Windows 下也能用,如下编译:
$ gcc -Wall -pipe -Wl,--export-dynamic,--export-all-symbols,--out-implib,libtestcall.a
-O3 -o testcall testcall.c
$ gcc -shared -Wall -pipe -O3 -o testlib.so testlib.c -L. -ltestcall
(测试环境:cygwin,要求 ld
$ ld --version
GNU ld version 2.14.90 20030901
Copyright 2002 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License. This program has absolutely no warranty.

               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/31179/showart_321412.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP