孙鑫MFC 19 章 动态链接库编程
来源:互联网 发布:nvsip监控软件下载 编辑:程序博客网 时间:2024/06/06 17:12
Windows API中的所有函数都包含在DLL中。其中有三个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。
静态库和动态库
静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件);
在使用动态库的时候,往往提供两个文件:一个因入库和一个DLL。因入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行时候,再去加载DLL,访问DLL中导出的函数。
使用动态链接库的好处
可以采用多种编程语言来编写。
增强产品的功能。
提供二次开发的平台。
简化项目管理
可以节省磁盘空间和内存。
有助于资源的共享。
有助于实现应用程序的本地化
建立DLL文件代码如下:
Dll.h
int _declspec(dllimport) add(int a, int b);//必须带_declspec(dllexport)文件,以生成*.lib文件
dll.cpp
#include "dll.h"
int _stdcall add(int a, int b)
{
returna + b;
}
链接的def 文件
LIBRARY dll
EXPORTS //自己的函数
add
如果要查找*dll中包含信息,比如说是否生成了函数调用,或者查看函数名字,可在命令行下进入Debug所在目录,输入以下命令
dumpbin -exports D:\Projects\C++\dll\Debug\dll.dll
发现函数名字已经被改成了?add@@YAHHH@Z,这种现象叫做名字粉碎,是为了支持函数重载而做的。
有些时候由于某种安装原因,dumpbin被认为是无效命令,接下来在
C:\Program Files\Microsoft Visual Studio\VC98\Bin\下找到VCVARS32.bat并在命令行运行,之后就能执行dumpbin命令了。
新建MFC程序,新建两个按钮,代码如下:
void CDllTestDlg::OnBtnAdd()
{
// TODO: Add your controlnotification handler code here
CString str;
str.Format("3+5=&d",Add(3,5));
MessageBox(str);
}
void CDllTestDlg::OnBtnSubtract()
{
// TODO: Add your controlnotification handler code here
CString str;
str.Format("5-3=%d",Subtract(5,3));
MessageBox(str);
}
为使编译器认识Add,Subtract,必须在之前使用两个声明:
extern int Add(int x,int y);
extern int Subtract(int x,int y);
可以使用标示符表示这两个函数是从动态链接库的.lib文件引用的,以生成效率更高的代码
_declspec(dllimport) int Add(int x,int y);
_declspec(dllimport) int Subtract(int x,int y);
这两段代码我们也可以在DLL中新建一个头文件放进去,并在MFC程序中添加头文件
如果要查看DllTest.exe文件信息,使用命令行dumpbin-imports dlltest.exe
修改动态链接库Dll.h
#ifdef DLL_API
#else
#define DLL_API _declspec(dllimport)
#endif
DLL_API int Add(int x,int y);
DLL_API int Subtract(int x,int y);
修改Dll.cpp文件
#define DLL_API _declspec(dllexport)
#include "Dll.h"
int Add(int x,int y)
{
return x+y;
}
int Subtract(int x,int y)
{
return x-y;
}
这样做是为了方便外部程序调用同时方便内部程序使用,因为动态链接库中只有导出的函数才可以被使用,没有导出的函数在外部是看不到的,是不能被访问的
我们希望导出的函数名不被改变,加extern "C"大写的C!即可,#define DLL1_API extern "C" _declspec(dllexport),但它只能导出全局函数,不能导出类的成员函数,并且如果调用约定被改成了别的方式,此时函数名也被改变。所以这种方式不太好。
解决之道是用模块定义文件。
a.新建dll2.dll工程;
b.加dll2.cpp中写两个函数add和subtract
c.在目录中新建dll2.def文件,增加到工程。
d.在dll2.def中加入如下代码:
LIBRARY Dll2EXPORTS
add
subtract
e.编译后用dumpbin查看函数名是否被改变?
此时你改变调用约定,函数名不会被改变,但如果你加上_stdcall定义函数,调用时也需要加入_stdcall,否则会出错!
静态加载的方法:
1、添加头文件#include "Dll.h"
2、引入Lib库 #pragma comment(lib,"Dll.lib")
3、这样就可以直接使用Dll.h中导入的函数
动态加载的方法:
HINSTANCEhandle = LoadLibrary("dll.dll");
typedefint(*addproc)(int, int); //typedefint(_stdcall *addproc)(int, int);
if(handle)
{
addprocmyadd = (addproc)GetProcAddress(handle,"?Add@@YAHHH@Z"); //这里的名字随着变化
if(myadd)
{
cout<< myadd(1, 2) << endl;
}
}
XX.def文件可以很好的解决 编译时,函数名字变化的问题
动态连接,如果要调用很多的dll文件时,这样可以节省内存
不需要连接lib对象,也不需要头文件,只需要一个dll文件即可。
- 孙鑫MFC 19 章 动态链接库编程
- 孙鑫MFC第十九章 动态链接库编程
- MFC 动态链接库
- mfc动态链接库
- MFC:动态链接库
- MFC动态链接库
- MFC动态链接库
- 孙鑫-MFC笔记十一--动态链接库
- VC++动态链接库编程之非MFC DLL
- VC++动态链接库编程之MFC扩展 DLL
- VC++动态链接库编程之MFC规则DLL
- VC++动态链接库编程之非MFC DLL
- VC++动态链接库编程之MFC规则DLL
- VC++动态链接库编程之MFC扩展 DLL
- VC++动态链接库编程之MFC扩展 DLL 1
- VC++动态链接库编程之MFC扩展 DLL 2
- VC++动态链接库编程之MFC扩展 DLL 3
- VC++动态链接库编程之非MFC DLL
- SGI STL空间配置器详解(一)-第一级空间配置器
- IE7.JS解决IE兼容性问题方法
- Aspose.Cells、NPOI、MyXls导出Excel
- 只有挣扎的现在,才是最好的状态(转)(文/王文华)
- Heritrix 和 Nutch的区别
- 孙鑫MFC 19 章 动态链接库编程
- UVA 11137 Ingenuous Cubrency(完全背包)
- AsyncTask源代码浅析(一)
- [原]Java web学习系列之 Java web开发中的SSH整合(Struts、Spring、Hibernate)(上)
- 第十二届中国国际半导体博览会暨高峰论坛签到凭证注册流程
- model checking
- 字符串的简单包含问题,主要看看转换问题的思路
- GetTickCount()函数的陷阱!
- Intent几种用法