您的位置:首页 > 编程语言 > C语言/C++

动态链接库 隐式链接 首次接触分歧定义(同样字段cpp中翻译为export 头文件里翻译为import)

2015-07-08 17:25 127 查看
前言

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>//新加的
然后就可以把测试工程里的函数声明都删掉了

现在只需要更换dll文件 就能使exe的功能改变 (偷偷将DLL的减法改为加法,然后替换DEBUG文件夹下原有的DLL)

分歧翻译使.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;
;
}


风行者引领群雄者行风
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: