前言
WIN API的所有函数都包含在DLL中,最重要的有三个DLL
Kernel32.dll管理内存 进程 和线程
User32.dll 窗口界面与消息
GDI32.dll 画图和显示文本
加载DLL的方式有两种 隐式链接 显示加载
两种方法对于你的程序调用动态库时没有任何区别,只是你在编程时,步骤是不一样的。显式调用麻烦了点,但可以没有相应的lib库;隐式调用,使用起来比较简单,有函数的声明就可以了,但必须有lib库。
隐式加载默认是加载到内存中的,始终占用内存。显示加载,你加载时占用内存,释放了就不占用内存了。如果该DLL已经载入,loadlibrary只是会增加一个引用计数,相同,freelibrary也只是减少引用计数,如果引用计数为0时,DLL才从内存中移除。
隐式链接的缺点:使用比较简单,在程序的其他部分可以任意使用函数,但是当程序访问十来个dll动态链接库的时候,此时如果都使用隐式链接的时候,启动此程序的时候,这十来个动态链接库都需要加载到内存,映射到内存的地址空间,这就会加大进程的启动时间
隐式链接
隐式的加载时链接的方法如下
DLL工程编译后 会产生两个文件 一个是DLL 一个是LIB
将LIB文件复制到testB文件夹里(textB与Debug和Release文件夹平级)
将DLL文件复制到Debug文件夹里(不复制编译能通过但不能运行)
==============================================================================
DLL工程为win32 dll 空文件工程
添加 cpp文件 jisuan.cpp
_declspec(dllexport) int add(int a,int b)
{
return a+b;
}
编译 产生DLL 和LIB
==============================================================================
测试端工程 为MFC对话框工程
在stdafx.h中
#pragma comment (lib,"0708A.lib")
在Dlg.cpp中
extern int add(int, int);
void CtestBDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
this->m_z=add(3,4);<span style="white-space:pre"> </span>//m_z是静态文本框成员 用来显示计算结果
this->UpdateData(0);
}
将LIB文件复制到testB文件夹里(textB与Debug和Release文件夹平级)
编译但不运行,生成Debug文件夹
将DLL文件复制到Debug文件夹里
运行,OK
为隐式链接提供头文件
至此 在应用端每使用一个函数都需要做一个声明
这样对DLL使用者不方便
可以提供给使用者一个 .h文件 使用者#include 这个.h 文件后 就不再需要对每个函数作声明了
为DLL工程添加.h 文件 jisuan.h
// 这个.h文件 是给应用端使用的 所以是import而不是export
_declspec(dllimport) int add(int,int);
_declspec(dllimport) int substract(int,int);
_declspec(dllimport) int multi(int,int);
_declspec(dllimport) int divide(int,int);
将这个头文件也复制到 lib 所在的文件夹下
为测试工程添加
#pragma comment (lib,"0709A.lib")
#include "jisuan.h"<span style="white-space:pre"> </span>//新加的
然后就可以把测试工程里的函数声明都删掉了
分歧翻译使.h文件既能被应用端外部引用
也能被.cpp文件引用(其实没啥用)
改造前的 .h 和.cpp文件
.h
// 这个.h文件 是给应用端使用的 所以是import而不是export
_declspec(dllimport) int add(int,int);
_declspec(dllimport) int substract(int,int);
_declspec(dllimport) int multi(int,int);
_declspec(dllimport) int divide(int,int);
.cpp
_declspec(dllexport) int add(int a,int b)
{
return a+b;
}
_declspec(dllexport) int substract(int a,int b)
{
return a-b;
}
_declspec(dllexport) int multi(int a,int b)
{
return a*b;
}
_declspec(dllexport) int divide(int a,int b)
{
if(b==0)
{
return 12345;
}
return a/b;
;
改造中的cpp
_declspec(dllexport) int add(int,int);
_declspec(dllexport) int substract(int,int);
_declspec(dllexport) int multi(int,int);
_declspec(dllexport) int divide(int,int);
int add(int a,int b)
{
return a+b;
}
int substract(int a,int b)
{
return a-b;
}
int multi(int a,int b)
{
return a*b;
}
int divide(int a,int b)
{
if(b==0)
{
return 12345;
}
return a/b;
;
}
改造后的 .h 和.cpp文件
.h
//改造后 这个.h文件既可以给应用端用 也可以帮本地的cpp文件作下声明(其实没啥用)
#ifndef __JISUAN_0709A__
#define __JISUAN_0709A__ _declspec(dllimport)
#endif
__JISUAN_0709A__ int add(int,int);
__JISUAN_0709A__ int substract(int,int);
__JISUAN_0709A__ int multi(int,int);
__JISUAN_0709A__ int divide(int,int);
.cpp
#define __JISUAN_0709A__ _declspec(dllexport)
#include "jisuan.h" //因为有上一句,头文件里的JISUAN将被翻译成export而不是import
int add(int a,int b)
{
return a+b;
}
int substract(int a,int b)
{
return a-b;
}
int multi(int a,int b)
{
return a*b;
}
int divide(int a,int b)
{
if(b==0)
{
return 12345;
}
return a/b;
;
}
风行者引领群雄者行风