首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

为 Linux 应用程序编写 DLL 实例

为 Linux 应用程序编写 DLL 实例

dll 示例:小的 C 程序和 dlTest动态链接装入器示例程序是一个小的 C 程序,该程序被设计用来练习 dl例程。该程序基于每个人都编写过的一个 C 程序,它将“HelloWorld”打印到控制台上。最初打印的消息是“HeLlOWoRlD”。该测试程序链接到再次打印该消息的两个函数上:第一次都用大写字符,第二次都用小写字符。
以下是该程序的概要:
  • 定义 dll include 文件           dlfcn.h 和所需的变量。至少需要这些变量:
    • 到共享库文件的句柄
    • 指向被映射函数入口点的指针
    • 指向错误字符串的指针
  • 打印初始消息,“HeLlO WoRlD”。
  • 使用绝对路径“/home/dlTest/UPPERCASE.so”和选项RTLD_LAZY,           dlopen 打开 UPPERCASE dll的共享目标文件并返回句柄。
    • 选项 RTLD_LAZY 推迟解析 dll 的外部引用,直到 dll 被执行。
    • 选项 RTLD_NOW 在               dlopen 返回之前解析所有的外部引用。
  • dlsym 返回入口点 printUPPERCASE 的地址。
  • 调用 printUPPERCASE 并且打印修改过的消息“HELLO WORLD”。
  • dlclose 关闭到 UPPERCASE.so的句柄,并且从内存中取消 dll 映射。
  • dlopen 使用基于环境变量 LD_LIBRARY_PATH的相对路径查找共享目标路径,来打开 lowercase dll 的共享目标文件lowercase.so,并且返回句柄。
  • dlsym 返回入口点 printLowercase 的地址。
  • 调用 printLowercase 并且打印修改过的信息“hello world”。
  • dlclose 关闭到 lowercase.so的句柄,并且从内存中取消 dll 映射。
注意,每次调用         dlopen 、         dlsym 或         dlclose 之后,调用         dlerror 以获取最后的错误信息,并且打印该错误信息字符串。以下是 dlTest的测试运行:      
1
2
3
4
5
6
7
8
9
10
11
12
   dlTest  2-Original message
HeLlO WoRlD
    dlTest  3-Open Library with absolute path return-(null)-
    dlTest  4-Find symbol printUPPERCASE return-(null)-
HELLO WORLD
    dlTest  5-printUPPERCASE return-(null)-
    dlTest  6-Close handle return-(null)-
    dlTest  7-Open Library with relative path return-(null)-
    dlTest  8-Find symbol printLowercase return-(null)-
hello world
    dlTest  9-printLowercase return-(null)-
    dlTest 10-Close handle return-(null)-




完整的 dlTest.c、UPPERCASE.c 和 lowercase.c源代码清单在本文后面的 里。      
构建 dlTest启用运行时动态链接需要三步:
  • 将 dll 编译为位置无关代码
  • 创建 dll 共享目标文件
  • 编译主程序并同 dl 库相链接
编译 UPPERCASE.c 和 lowercase.c 的 gcc 命令包含 -fpic 选项。选项-fpic 和 -fPIC导致生成的代码是位置无关的,重建共享目标库需要位置无关。-fPIC选项产生位置无关的代码,这类代码支持大偏移。用于 UPPERCASE.o 和lowercase.o 的第二个 gcc 命令,带有 -shared选项,该选项产生适合于动态链接的共享目标文件 a*.so。
用于编译和执行 dltest 的 ksh 脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/ksh
#  Build shared library
#
#set -x
clear
#
#  Shared library for dlopen absolute path test
#
if [ -f UPPERCASE.o ]; then rm UPPERCASE.o
fi
gcc  -c -fpic UPPERCASE.c
if [ -f UPPERCASE.so ]; then rm UPPERCASE.so
fi
gcc -shared -lc  -o UPPERCASE.so  UPPERCASE.o
#
#  Shared library for dlopen relative path test
#
export LD_LIBRARY_PATH=`pwd`
if [ -f lowercase.o ]; then rm lowercase.o
fi
gcc  -c -fpic lowercase.c
if [ -f lowercase.so ]; then rm lowercase.so
fi
gcc -shared -lc  -o lowercase.so  lowercase.o
#
#  Rebuild test program
#
if [ -f dlTest ]; then rm dlTest
fi
gcc -o dlTest dlTest.c -ldl
echo Current LD_LIBRARY_PATH=$LD_LIBRARY_PATH
dlTest




结束语创建能在运行时被动态链接到 Linux系统上的应用程序的共享目标代码是一项非常简单的练习。应用程序通过使用对动态链接装入器的dlopen、dlsym 和 dlclose函数调用来获取对共享目标文件的访问。dlerror以字符串的形式返回任何错误,这些错误信息字符串描述 dl函数碰到的最后一个错误。在运行时,主应用程序使用绝对路径或相对于LD_LIBRARY_PATH 的相对路径找到共享目标库,并且请求所需的 dll入口点的地址。当需要时,也可对 dll进行间接函数调用,最后,关闭到共享目标文件的句柄,并且从内存中取消该目标文件映射,使之不可用。
使用附加选项 -fpic 或 -fPIC编译共享目标代码,以产生位置无关的代码,使用 -shared选项将目标代码放进共享目标库中。
Linux中的共享目标代码库和动态链接装入器向应用程序提供了额外的功能。减少了磁盘上和内存里的可执行文件的大小。可以在需要时,装入可选的应用程序功能,可以在无须重新构建整个应用程序的情况下修正缺陷,并且应用程序可以包含第三方的插件。
返回列表