为Linu应用程序编写DLL

上传人:jin****ng 文档编号:220189038 上传时间:2023-06-29 格式:DOCX 页数:32 大小:29.48KB
收藏 版权申诉 举报 下载
为Linu应用程序编写DLL_第1页
第1页 / 共32页
为Linu应用程序编写DLL_第2页
第2页 / 共32页
为Linu应用程序编写DLL_第3页
第3页 / 共32页
资源描述:

《为Linu应用程序编写DLL》由会员分享,可在线阅读,更多相关《为Linu应用程序编写DLL(32页珍藏版)》请在装配图网上搜索。

1、为 Linux 应用程序编写 DLL为 Linux 应用程序编写 DLL来源: ChinaUnix 博客 日期: 2009.07.15 15:57 (共有 0 条评论) 我要评 论Linux 动态链接Linux 中的应用程序以以下两种方式之一链接到外部函数:要么在构建时 与静态库( lib*.a ) 静态地链接,并且将库代码包含在该应用程序的可 执行文件里;要么在运行时与共享库( lib*.so ) 动态地链接。通过动态 链接装入器,将动态库映射进应用程序的可执行内存中。在启动应用程序 之前,动态链接装入器将所需的共享目标库映射到应用程序的内存,或者 使用系统共享的目标并为应用程序解析所需的外

2、部引用。现在应用程序就 可以运行了。作为示例,下面有一个演示 Linux 中对动态链接库的缺省使用的小程序: main()printf("Hello world ");当使用 gcc 编译 hello.c 时,就创建了一个名为 a.out 的可执行文件。通 过使用 Linux 命令 ldd a.out (该命令打印出共享库的相互依赖性),可以 看出所需的共享库是:libc.so.6 => /lib/libc.so.6 (0x4001d000)/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 使用相同的动态

3、链接装入器在应用程序运行之后将 dll 映射进应用程序 的内存。通过使用 Linux 动态装入器例程,应用程序控制装入哪一个动态 库以及调用库中的哪一个函数,以执行装入和链接以及返回所需入口点的 地址。回页首Linux dll 函数Linux 提供 4 个库函数( dlopen , dlerror , dlsym 和 dlclose ),一个include 文件( dlfcn.h )以及两个共享库(静态库 libdl.a 和动态库libdl.so ),以支持动态链接装入器。这些库函数是:dlopen 将共享目标文件打开并且映射到内存中,并且返回句柄dlsym 返回一个指向被请求入口点的指针dl

4、error 返回 NULL 或者一个指向描述最近错误的 ASCII 字符串的指针dlclose 关闭句柄并且取消共享目标文件的映射动态链接装入器例程 dlopen 需要在文件系统中查找共享目标文件以打开文件并创建句柄。有 4 种方式用以指定文件的位置:dlopen call 中的绝对文件路径在 LD_LIBRARY_PATH 环境变量中指定的目录中在 /etc/ld.so.cache 中指定的库列表之中先在 /usr/lib 之中,然后在 /lib 之中回页首dll 示例:小的 C 程序和 dlTest动态链接装入器示例程序是一个小的 C 程序,该程序被设计用来练习 dl 例程。该程序基于每个

5、人都编写过的一个C程序,它将“Hello World”打 印到控制台上。最初打印的消息是“HeLlO WoRID”。该测试程序链接到再 次打印该消息的两个函数上:第一次都用大写字符,第二次都用小写字符。 以下是该程序的概要:定义 dll include 文件 dlfcn.h 和所需的变量。至少需要这些变量到共享库文件的句柄指向被映射函数入口点的指针指向错误字符串的指针打印初始消息,“ HeLIO WoRID”。dIopen使用绝对路径 “/home/dITest/UPPERCASE.so” 和选项 RTLD_LAZY,打开 UPPERCASE dII 的共享目标文件并返回句柄。选项 RTLD_

6、LAZY 推迟解析 dII 的外部引用,直到 dII 被执行。选项 RTLD_NOW 在 dIopen 返回之前解析所有的外部引用。dIsym 返回入口点 printUPPERCASE 的地址。调用printUPPERCASE并且打印修改过的消息“HELLO WORLD”。dlclose 关闭到 UPPERCASE.so 的句柄,并且从内存中取消 dll 映射。dlopen 使用基于环境变量 LD_LIBRARY_PATH 的相对路径查找共享目标路 径,来打开 lowercase dll 的共享目标文件 lowercase.so ,并且返回句柄。dlsym 返回入口点 printLowerca

7、se 的地址。调用printLowercase并且打印修改过的信息“hello world”。dlclose 关闭到 lowercase.so 的句柄,并且从内存中取消 dll 映射。 注意,每次调用 dlopen 、 dlsym 或 dlclose 之后,调用 dlerror 以获取 最后的错误信息,并且打印该错误信息字符串。以下是 dlTest 的测试运行: dlTest 2-Original messageHeLlO WoRlDdlTest 3-Open Library with absolute path return-(null)-dlTest 4-Find symbol print

8、UPPERCASE return-(null)-HELLO WORLDdlTest5-printUPPERCASE return-(null)-dlTest6-Close handle return-(null)-dlTest7-Open Library with relative path return-(null)-dlTest8-Find symbol printLowercase return-(null)-hello worlddlTest 9-printLowercase return-(null)- dlTest 10-Close handle return-(null)-完整的

9、 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 选项,该

10、 选项产生适合于动态链接的共享目标文件 a*.so。用于编译和执行 dltest 的 ksh 脚本如下:#!/bin/ksh# Build shared library#set -xclear# Shared library for dlopen absolute path test#if -f UPPERCASE.o ; then rm UPPERCASE.ofigcc -c -fpic UPPERCASE.cif -f UPPERCASE.so ; then rm UPPERCASE.sofigcc -shared -lc -o UPPERCASE.so UPPERCASE.o# Shar

11、ed library for dlopen relative path test#export LD_LIBRARY_PATH二pwdif -f lowercase.o ; then rm lowercase.o fi gcc -c -fpic lowercase.c if -f lowercase.so ; then rm lowercase.sofigcc -shared -lc -o lowercase.so lowercase.o# Rebuild test program#if -f dlTest ; then rm dlTestfigcc -o dlTest dlTest.c -l

12、dlecho Current LD_LIBRARY_PATH=$LD_LIBRARY_PATHdlTest回页首结束语 创建能在运行时被动态链接到 Linux 系统上的应用程序的共享目标代码 是一项非常简单的练习。应用程序通过使用对动态链接装入器的 dlopen、 dlsym和dlclose函数调用来获取对共享目标文件的访问。dlerror以字符 串的形式返回任何错误,这些错误信息字符串描述 dl 函数碰到的最后一 个错误。在运行时,主应用程序使用绝对路径或相对于 LD_LIBRARY_PATH 的相对路径找到共享目标库,并且请求所需的 dll 入口点的地址。当需要 时,也可对 dll 进行间

13、接函数调用,最后,关闭到共享目标文件的句柄, 并且从内存中取消该目标文件映射,使之不可用。使用附加选项 -fpic 或 -fPIC 编译共享目标代码,以产生位置无关的代码, 使用 -shared 选项将目标代码放进共享目标库中。Linux 中的共享目标代码库和动态链接装入器向应用程序提供了额外的功 能。减少了磁盘上和内存里的可执行文件的大小。可以在需要时,装入可 选的应用程序功能,可以在无须重新构建整个应用程序的情况下修正缺陷 并且应用程序可以包含第三方的插件。回页首清单(应用程序和 dll)dlTest.c:/*/*Test Linux Dynamic Function Loading*/*

14、/*void*dlopen(const char *filename, int flag)*/*Opens dynamic library and return handle*/*/*const char *dlerror(void) */*Returns string describing the last error.*/*/*void*dlsym(void *handle, char *symbol)*/*Return pointer to symbol's load point.*/*If symbol is undefined, NULL is returned.*/*/*i

15、ntdlclose (void *handle)*/*Close the dynamic library handle.*/*/*/*/#include#include/*/* 1-dll include file and variables */*/#includevoid *FunctionLib;int (*Function)();/* Handle to shared lib file */* Pointer to loaded routine */* Pointer to error string */const char *dlError;main( argc, argv )int

16、 rc;/* return codes */char HelloMessage = "HeLlO WoRlDn"/*/* 2-print the original message*/*/printf(" dlTest 2-Original message n");printf("%s", HelloMessage);/*/* 3-Open Dynamic Loadable Libary with absolute path*/FunctionLib = dlopen("/home/dlTest/UPPERCASE.so&qu

17、ot;,RTLD_LAZY);dlError = dlerror();printf(" dlTest 3-Open Library with absolute path return-%s-n", dlError);if( dlError ) exit(1);/*/* 4-Find the first loaded function */*/Function= dlsym( FunctionLib, "printUPPERCASE");dlError = dlerror();printf(" dlTest 4-Find symbol print

18、UPPERCASE return-%s- n", dlError);if( dlError ) exit(1);/*/* 5-Execute the first loaded function/*/rc = (*Function)( HelloMessage );printf(" dlTest 5-printUPPERCASE return-%s- n", dlError);/*/* 6-Close the shared library handle */* Note: after the dlclose, "printUPPERCASE" i

19、s not loaded*/*/rc = dlclose(FunctionLib);dlError = dlerror();printf(" dlTest 6-Close handle return-%s-n",dlError);if( rc ) exit(1);/*/* 7-Open Dynamic Loadable Libary using LD_LIBRARY path*/*/FunctionLib = dlopen("lowercase.so",RTLD_LAZY);dlError = dlerror();printf(" dlTest

20、 7-Open Library with relative path return-%s- n", dlError);if( dlError ) exit(1);/*/* 8-Find the second loaded function*/*/Function= dlsym( FunctionLib, "printLowercase");dlError = dlerror();printf(" dlTest 8-Find symbol printLowercase return-%s- n",dlError);if( dlError ) ex

21、it(1);/*/* 8-execute the second loaded function*/*/rc = (*Function)( HelloMessage );printf(" dlTest 9-printLowercase return-%s- n", dlError);/*/* 10-Close the shared library handle/*/rc = dlclose(FunctionLib);dlError = dlerror();printf(" dlTest 10-Close handle return-%s-n",dlErro

22、r); if( rc ) exit(1);return(0);UPPERCASE.c:*/*Function to print input string as UPPER case.*/*Returns1.*/*/int printUPPERCASE ( inLine ) char inLine;char UPstring256;char *inptr, *outptr;inptr = inLine; outptr = UPstring;while ( *inptr != '0' ) *outptr+ = toupper(*inptr+); *outptr+ = '0&

23、#39; printf(UPstring);return(1);lowercase.c/* /* Function to print input string as lower case. */*Returns 2.*/int printLowercase( inLine )char inLine;char lowstring256;char *inptr, *outptr;inptr = inLine;outptr = lowstring;while ( *inptr != '' )*outptr+ = tolower(*inptr+);*outptr+ = '

24、9; printf(lowstring);return(2);自己实现的第一个linux中dll的调用1. 编译 dll:g+ -shared -lc -o strcase.dll lowcase.cpp uppercase.cpp如果要加入调试信息:(加上 -g 选项)g+ -shared -lc -o strcase.dll lowcase.cpp uppercase.cpp -g编译 c+ dll 注意函数之前需要加上 extern "C", 否则在 dlsym 函 数调用的时候可能会找不到函数2. 编译 exe:g+ -ldl -o strcase.exe main

25、.cpp如果要加入调试信息:(加上 -g 选项)g+ -ldl -o strcase.exe main.cpp -g3. gdb 调试gdb strcase.exe调试时需要在编译的时候加上(-g)选项gdb 命令:b 设置断点, 例如:b main # 表示跳到 main 函数b main.cpp: 56 #56 表示行号l 打印当前的执行代码附近的 10 行p 打印变量 szMsg 的值p szMsgn 执行下一行(单步执行 , 类似 VC 中的 F10)s 进入函数 ( 类似 VC 中的 F10)r 开始执行/main.cppCpp 代码<SPAN style="FONT

26、-SIZE: medium"><SPAN style="COLOR: #3366ff">#include <iostream>#include <stdlib.h>#include <dlfcn.h>using namespace std;#define TRUE 1#define FALSE 0typedef int BOOL;typedef void (*PFUN_STRING)(char* pszStr);BOOL UseDll(char* szMsg);int main()char szMsg = &q

27、uot;Hello, andylin!"/调用 dllUseDll(szMsg);return 0;BOOL UseDll(char* szMsg)void* hDll = NULL;char* szDllErr = NULL;PFUN_STRING pfunUpper = NULL;PFUN_STRING pfunLower = NULL;if (NULL = szMsg)return FALSE;cout << "The Origin String:" << szMsg << endl;/open dllhDll = dlo

28、pen("./strcase.dll", RTLD_LAZY);szDllErr = dlerror();if (szDllErr)cout << "open uppercase.dll error! err info:" << szDllErr<< endl;return FALSE;/find the functionpfunUpper = (PFUN_STRING)dlsym(hDll, "StrUpper");szDllErr = dlerror();if (szDllErr)cout &l

29、t;< "find function StrUpper Error! err info:" <<szDllErr << endl;return FALSE;(*pfunUpper)(szMsg);cout << "after StrUpper string:" << szMsg << endl;/call StrLowerpfunLower = (PFUN_STRING)dlsym(hDll, "StrLower");szDllErr = dlerror();if (s

30、zDllErr)cout << "find function StrLower Error! err info:" << szDllErr << endl;return FALSE;(* pfunLower)(szMsg);cout << "after StrLower string:" << szMsg << endl;/close handleint nRet = dlclose(hDll);szDllErr = dlerror();cout << "clo

31、se dll info:" << szDllErr << endl;</SPAN></SPAN>#include <iostream>#include <stdlib.h>#include <dlfcn.h> using namespace std;#define TRUE 1#define FALSE 0typedef int BOOL;typedef void (*PFUN_STRING)(char* pszStr);BOOL UseDll(char* szMsg);int main()char

32、szMsg = "Hello, andylin!"/调用 dllUseDll(szMsg);return 0;BOOL UseDll(char* szMsg)void* hDll = NULL;char* szDllErr = NULL;PFUN_STRING pfunUpper = NULL;PFUN_STRING pfunLower = NULL;if (NULL = szMsg)return FALSE;cout << "The Origin String:" << szMsg << endl;/open dll

33、hDll = dlopen("./strcase.dll", RTLD_LAZY);szDllErr = dlerror();if (szDllErr)cout << "open uppercase.dll error! err info:" << szDllErr<< endl;return FALSE;/find the functionpfunUpper = (PFUN_STRING)dlsym(hDll, "StrUpper");szDllErr = dlerror();if (szDllE

34、rr)cout << "find function StrUpper Error! err info:" << szDllErr << endl;return FALSE;(*pfunUpper)(szMsg);cout << "after StrUpper string:" << szMsg << endl;/call StrLowerpfunLower = (PFUN_STRING)dlsym(hDll, "StrLower");szDllErr = dler

35、ror();if (szDllErr)cout << "find function StrLower Error! err info:" <<szDllErr << endl;return FALSE;(* pfunLower)(szMsg);cout << "after StrLower string:" << szMsg << endl;/close handleint nRet = dlclose(hDll);szDllErr = dlerror();cout <<

36、 "close dll info:" << szDllErr << endl;/lowcase.cppCpp 代码 style="COLOR: #3366ff">#include <stdio.h><SPANstyle="FONT-SIZE:medium"><SPAN#include <stdlib.h>#include <iostream>using namespace std;extern "C" void StrLower(c

37、har* pszStr)if (NULL = pszStr)return;int nLen = 0;int i = 0;nLen = strlen(pszStr);for (i = 0; i < nLen; i+)if ( (pszStri >= 'A') && (pszStri <= 'Z') )pszStri += 'a' - 'A'</SPAN></SPAN>#include <stdio.h>#include <stdlib.h>#inclu

38、de <iostream>using namespace std;extern "C" void StrLower(char* pszStr) if (NULL = pszStr)return;int nLen = 0;int i = 0;nLen = strlen(pszStr);for (i = 0; i < nLen; i+) if ( (pszStri >= 'A') && (pszStri <= 'Z') )pszStri += 'a' - 'A'/upp

39、ercase.cppCpp 代码<SPAN style="FONT-SIZE: medium"><SPANstyle="COLOR: #3366ff">#include <stdio.h>#include <stdlib.h>#include <iostream>using namespace std;extern "C" void StrUpper(char* pszStr)if (NULL = pszStr)return;int nLen = 0;int i = 0;nLen = strlen(pszStr);for (i = 0; i < nLen; i+)if ( (pszStri >= 'a') && (pszStri <= 'z') )pszStri -= 'a' - 'A'</SPAN></SPAN>

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!