免费预览已结束,剩余38页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
为 Linux 应用程序编写 DLL 为 Linux 应用程序编写 DLL 来源: ChinaUnix博客 日期: 2009.07.15 15:57(共有0条评论) 我要评论 Linux 动态链接Linux 中的应用程序以以下两种方式之一链接到外部函数:要么在构建时与静态库( lib*.a ) 静态地链接,并且将库代码包含在该应用程序的可执行文件里;要么在运行时与共享库( lib*.so ) 动态地链接。通过动态链接装入器,将动态库映射进应用程序的可执行内存中。在启动应用程序之前,动态链接装入器将所需的共享目标库映射到应用程序的内存,或者使用系统共享的目标并为应用程序解析所需的外部引用。现在应用程序就可以运行了。 作为示例,下面有一个演示 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)使用相同的动态链接装入器在应用程序运行之后将 dll 映射进应用程序的内存。通过使用 Linux 动态装入器例程,应用程序控制装入哪一个动态库以及调用库中的哪一个函数,以执行装入和链接以及返回所需入口点的地址。回页首Linux dll 函数Linux 提供 4 个库函数( dlopen , dlerror , dlsym 和 dlclose ),一个 include 文件( dlfcn.h )以及两个共享库(静态库 libdl.a 和动态库 libdl.so ),以支持动态链接装入器。这些库函数是: dlopen 将共享目标文件打开并且映射到内存中,并且返回句柄 dlsym返回一个指向被请求入口点的指针 dlerror 返回 NULL 或者一个指向描述最近错误的 ASCII 字符串的指针 dlclose关闭句柄并且取消共享目标文件的映射 动态链接装入器例程 dlopen 需要在文件系统中查找共享目标文件以打开文件并创建句柄。有 4 种方式用以指定文件的位置:dlopen call 中的绝对文件路径 在 LD_LIBRARY_PATH 环境变量中指定的目录中 在 /etc/ld.so.cache 中指定的库列表之中 先在 /usr/lib 之中,然后在 /lib 之中 回页首dll 示例:小的 C 程序和 dlTest动态链接装入器示例程序是一个小的 C 程序,该程序被设计用来练习 dl 例程。该程序基于每个人都编写过的一个 C 程序,它将“Hello World”打印到控制台上。最初打印的消息是“HeLlO WoRlD”。该测试程序链接到再次打印该消息的两个函数上:第一次都用大写字符,第二次都用小写字符。以下是该程序的概要:定义 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 的测试运行: dlTest 2-Original message HeLlO WoRlDdlTest 3-Open Library with absolute path return-(null)- dlTest 4-Find symbol printUPPERCASE return-(null)- HELLO WORLDdlTest 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 worlddlTest 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 脚本如下:#!/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 # Shared library for dlopen relative path test#export LD_LIBRARY_PATH=pwdif -f lowercase.o ; then rm lowercase.ofigcc -c -fpic lowercase.cif -f lowercase.so ; then rm lowercase.s ofigcc -shared -lc -o lowercase.so lowercase.o# Rebuild test program#if -f dlTest ; then rm dlTestfigcc -o dlTest dlTest.c -ldlecho Current LD_LIBRARY_PATH=$LD_LIBRARY_PATHdlTest回页首结束语创建能在运行时被动态链接到 Linux 系统上的应用程序的共享目标代码是一项非常简单的练习。应用程序通过使用对动态链接装入器的 dlopen、dlsym 和 dlclose 函数调用来获取对共享目标文件的访问。dlerror 以字符串的形式返回任何错误,这些错误信息字符串描述 dl 函数碰到的最后一个错误。在运行时,主应用程序使用绝对路径或相对于 LD_LIBRARY_PATH 的相对路径找到共享目标库,并且请求所需的 dll 入口点的地址。当需要时,也可对 dll 进行间接函数调用,最后,关闭到共享目标文件的句柄,并且从内存中取消该目标文件映射,使之不可用。使用附加选项 -fpic 或 -fPIC 编译共享目标代码,以产生位置无关的代码,使用 -shared 选项将目标代码放进共享目标库中。Linux 中的共享目标代码库和动态链接装入器向应用程序提供了额外的功能。减少了磁盘上和内存里的可执行文件的大小。可以在需要时,装入可选的应用程序功能,可以在无须重新构建整个应用程序的情况下修正缺陷,并且应用程序可以包含第三方的插件。回页首清单(应用程序和 dll)dlTest.c:/*/* Test Linux Dynamic Function Loading */* */* 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 symbols load point. */* If symbol is undefined, NULL is returned. */* */* int dlclose (void *handle) */* Close the dynamic library handle. */* */* */* */*/#include#include /* */* 1-dll include file and variables */* */#include void *FunctionLib; /* Handle to shared lib file */int (*Function)(); /* Pointer to loaded routine */const char *dlError; /* Pointer to error string */main( argc, argv )int rc; /* return code s */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",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 printUPPERCASE 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" is 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 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 ) exit(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",dlError); if( rc ) exit(1);return(0);UPPERCASE.c:/*/* Function to print input string as UPPER case. */* Returns 1. */* */int printUPPERCASE ( inLine )char inLine;char UPstring256;char *inptr, *outptr; inptr = inLine;outptr = UPstring;while ( *inptr != 0 )*outptr+ = toupper(*inptr+);*outptr+ = 0;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+ = ;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.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-SIZE: medium"><SPAN style="COLOR: #3366ff">#include <iostream> #include <stdlib.h> #include <dlfcn.h> using namespace std; #define TRUE 1 #define FALSE 0 typedef int BOOL; typedef void (*PFUN_STRING)(char* pszStr); BOOL UseDll(char* szMsg); int main() char szMsg = "Hello, andylin!" /调用dll UseDll(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 hDll = dlopen("./strcase.dll", RTLD_LAZY); szDllErr = dlerror(); if (szDllErr) cout << "open uppercase.dll error! err info:" << szDllErr << endl; return FALSE; /find the function pfunUpper = (PFUN_STRING)dlsym(hDll, "StrUpper"); szDllErr = dlerror(); if (szDllErr) cout << "find function StrUpper Error! err info:" << szDllErr << endl; return FALSE; (*pfunUpper)(szMsg); cout << "after StrUpper string:" << szMsg << endl; /call StrLower pfunLower = (PFUN_STRING)dlsym(hDll, "StrLower"); szDllErr = dlerror(); if (szDllErr) cout << "find function StrLower Error! err info:" << szDllErr << endl; return FALSE; (* pfunLower)(szMsg); cout << "after StrLower string:" << szMsg << endl; /close handle int nRet = dlclose(hDll); szDllErr = dlerror(); cout << "close dll info:" << szDllErr << endl; </SPAN></SPAN> #include <iostream>#include <stdlib.h>#include <dlfcn.h>using namespace std;#defineTRUE1#define FALSE0typedef int BOOL;typedef void (*PFUN_STRING)(char* pszStr);BOOL UseDll(char* szMsg);int main()char 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 dllhDll = 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 (szDllErr)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 = dlerror();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 << "close dll info:" << szDllErr << endl;/lowcase.cppCpp代码 <SPAN style="FONT-SI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 订做门窗安装合同范本
- 2025广西师范大学劳动合同制员工招聘1人参考题库含答案详解(预热题)
- 2025年大学《化妆品技术与工程-化妆品质量控制与检测》考试备考试题及答案解析
- 2025年大学《水族科学与技术-水族箱设计与造景》考试参考题库及答案解析
- 2025广西南宁大桥镇乡村振兴工作站招聘信息员1人参考题库及答案详解一套
- 2025年大学《商务经济学-市场分析与预测》考试模拟试题及答案解析
- 2025年大学《医疗产品管理-医疗产品注册与审批》考试模拟试题及答案解析
- 2025广东珠海市金湾区平沙镇招聘第一批工作人员6人参考题库含答案详解(考试直接用)
- 第一单元第一课时《千以内数的认识》(教学设计)-2023-2024学年青岛版五四制数学二年级下册
- 2025年大学《创业管理-新企业注册与合规》考试备考题库及答案解析
- 英语语音语调的教学课件
- 2025年四川监理员考试题库附答案
- 绿色企业创建培训课件
- 家长课堂健康与饮食
- 骨科康复护理概述及康复功能评定
- 不确定条件下跨区域应急物资调度优化研究
- (高清版)DB12∕T 1444-2025 博物馆消防安全管理导则
- 建筑工程重大隐患排查整治方案
- 腰椎骨折疑难病例讨论
- 2025年广东省中考数学试卷真题(含答案详解)
- 乡风文明建设课件
评论
0/150
提交评论