动态链接库:我们经常把常用的代码制作成一个可执行模块供其他可执行文件调用,这样的模块称为链接库,分为动态链接库和静态链接库。

对于静态链接库,LIB包含具体实现代码且会被包含进EXE中,导致文件过大,浪费磁盘和内存;

对于动态链接库,DLL不必被包含在最终的EXE中,EXE执行时可以动态地装载和卸载DLL文件。

导出函数

将函数声明为导出函数有两种方式:

1、 在函数声明上加上_declspec(dllexport):

如:extern "C" int__declspec(dllexport)add(int x, int y);

2、 在.def文件中声明:如:

; lib.def : 导出DLL函数

LIBRARY dllTest(dll名称可忽略,但需要和生成的名称一致)

EXPORTS

Add @ 1

以”;”开始的为注释行,上述例子表示:生成名为“dllTest”的动态链接库,导出其中的add函数,序号为1。该序号在函数调用时起作用:GetProcAddress ( hDll, MAKEINTRESOURCE ( n ))返回 def定义的第n个函数地址。

DLL调用

使用动态链接库的时,往往提供两个文件:引入库文件(LIB)和动态链接库(DLL)。引入库文件(LIB)包含动态连接库(DLL)所有导出的函数和变量的符号名和地址,动态连接库(DLL)包含实际的函数和数据。调用方式分为动态调用(显式链接)和静态调用(隐式链接)。

1、 静态调用(隐式链接)

由编译系统完成对DLL的加载和卸载。共需两步操作:

告诉编译器与DLL相对应的LIB文件所在的路径及文件名,如#pragma comment (lib,"dllTest.lib") ;

声明导入函数,如:extern "C" __declspec(dllimport)add(int x,int y)(若有导出函数声明的头文件可直接包含该.h文件);

2、 动态调用(显示链接)

使用Win32 API 函数LoadLibrary、GetProcAddress、FreeLibrary实现"DLL加载-DLL函数地址获取-DLL释放”。这种方法不需要LIB文件,只需要DLL文件即可,显式链接速度更快且更加灵活。

关于DLL放置路径:

使用显式链接,在函数LoadLibrary的参数中可以指定DLL文件的完整路径;如果不指定路径,或者进行隐式链接,Windows将遵循下面的搜索顺序来定位DLL:

(1)包含EXE文件的目录

(2)工程目录

(3)Windows系统目录

(4)Windows目录

(5)列在Path环境变量中的一系列目录

例:

1、 生成DLL

创建Win32控制台的DLL项目MyDll,新建mydll.h和mydll.cpp,源码如下:

//mydll.h文件
#ifndef _MYDLL_H
#define _MYDLL_H
extern "C" int __declspec(dllexport)add(int x, int y);
#endif
//mydll.cpp文件
#include "mydll.h"
int add(int x, int y)
{
return x + y;
}

编译(F7)生成MyDll.lib和MyDll.dll。(extern "C"指定导出函数为c链接,避免C/C++命名规则不同导致的函数名不一致)

2、 调用DLL

创建Win32控制台项目,新建test.cpp文件,源码如下:

动态调用:(将MyDll.dll拷贝至工程目录)

#include <stdio.h>
#include <windows.h>
typedef int(*lpAddFun)(int, int); //宏定义函数指针类型
int main(int argc, char *argv[])
{
HINSTANCE hDll = LoadLibrary("MyDll.dll");//加载DLL
if (hDll != NULL)
{
lpAddFun addFun = (lpAddFun)GetProcAddress(hDll, "add");//获取函数地址
if (addFun != NULL)
{
int result = addFun(2, 3);
printf("%d", result);
}
FreeLibrary(hDll);//卸载DLL
}
return 0;
}

静态调用:(将MyDll.dll和MyDll.lib拷贝至工程目录)

#pragma comment(lib,"MyDll.lib")
extern "C" __declspec(dllimport) int add(int x,int y);
#include <stdio.h>
int main(int argc, char* argv[])
{
int result = add(2,3);
printf("%d",result);
return 0;
}

有时DLL导出函数若很多,在静态调用时,为了避免逐个写出extern "C"__declspec(dllimport) function(),可以直接包含DLL头文件(若有的话)。对于DLL制作者来说,需要实现头文件中函数是导入还是导出的自动转换,这时可通过定义宏实现。在DLL工程中头文件作用为导出声明,在应用工程中该头文件为导出声明。这时,DLL工程MyDll源码如下:

//mydll.h文件
#ifndef _MYDLL_H
#define _MYDLL_H
#ifdef MYDLL_EXPORT
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
extern "C" MYDLL_API int add(int x, int y);
#endif
// mydll.cpp文件
#define MYDLL_EXPORT //只在DLL实现中定义此符号
#include "mydll.h"
int add(int x, int y)
{
return x + y;
}

静态调用:(将MyDll.dll,MyDll.lib, mydll.h拷贝至工程目录)

#pragma comment(lib,"MyDll.lib")
#include"mydll.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
int result = add(2,3);
printf("%d",result);
return 0;
}

参考:

http://www.cnblogs.com/chio/archive/2007/11/03/948480.html#undefined

http://www.cnblogs.com/fangyukuan/archive/2010/06/20/1761464.html

http://www.cppblog.com/amazon/archive/2009/09/04/95318.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

动态链接库(DLL) 分类: c/c++ 2015-01-04 23:30 423人阅读 评论(0) 收藏的更多相关文章

  1. HDU2680 Choose the best route 最短路 分类: ACM 2015-03-18 23:30 37人阅读 评论(0) 收藏

    Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  2. android开发之调试技巧 分类: android 学习笔记 2015-07-18 21:30 140人阅读 评论(0) 收藏

    我们都知道,android的调试打了断点之后运行时要使用debug as->android application 但是这样的运行效率非常低,那么我们有没有快速的方法呢? 当然有. 我们打完断点 ...

  3. HDU 1272 小希的迷宫(并查集) 分类: 并查集 2015-07-07 23:38 2人阅读 评论(0) 收藏

    Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就 ...

  4. MS SQL数据批量备份还原(适用于MS SQL 2005+) 分类: SQL Server 数据库 2015-03-10 14:32 103人阅读 评论(0) 收藏

    我们知道通过Sql代理,可以实现数据库的定时备份功能:当数据库里的数据库很多时,备份一个数据库需要建立对应的定时作业,相对来说比较麻烦: 还好,微软自带的osql工具,比较实用,通过在命令行里里输入命 ...

  5. NYOJ-289 苹果 289 AC(01背包) 分类: NYOJ 2014-01-01 21:30 178人阅读 评论(0) 收藏

    #include<stdio.h> #include<string.h> #define max(x,y) x>y?x:y struct apple { int c; i ...

  6. ubuntu14.04使用root用户登录桌面 分类: 学习笔记 linux ubuntu 2015-07-05 10:30 199人阅读 评论(0) 收藏

    ubuntu安装好之后,默认是不能用root用户登录桌面的,只能使用普通用户或者访客登录.怎样开启root用户登录桌面呢? 先用普通用户登录,然后切换到root用户,然后执行如下命令: vi /usr ...

  7. Matlab调用C程序 分类: Matlab c/c++ 2015-01-06 19:18 464人阅读 评论(0) 收藏

    Matlab是矩阵语言,如果运算可以用矩阵实现,其运算速度非常快.但若运算中涉及到大量循环,Matlab的速度令人难以忍受的.当必须使用for循环且找不到对应的矩阵运算来等效时,可以将耗时长的函数用C ...

  8. Mahout快速入门教程 分类: B10_计算机基础 2015-03-07 16:20 508人阅读 评论(0) 收藏

    Mahout 是一个很强大的数据挖掘工具,是一个分布式机器学习算法的集合,包括:被称为Taste的分布式协同过滤的实现.分类.聚类等.Mahout最大的优点就是基于hadoop实现,把很多以前运行于单 ...

  9. 各种排序算法的分析及java实现 分类: B10_计算机基础 2015-02-03 20:09 186人阅读 评论(0) 收藏

    转载自:http://www.cnblogs.com/liuling/p/2013-7-24-01.html 另可参考:http://gengning938.blog.163.com/blog/sta ...

随机推荐

  1. 【Nginx】负载均衡

    本文介绍的负载均衡是针对的客户端请求在多个Nginx进程之间的均衡.注意与客户端请求在多个后端服务器之间的均衡相区别. 负载均衡问题的产生 在nginx中,建立连接的时候,会设计负载均衡问题.在多个子 ...

  2. markdown 插入latex公式练习

    markdown 插入latex公式 $$公式$$表示行间公式,本来Tex中使用\(公式\)表示行内公式,但因为Markdown中\是转义字符,所以在Markdown中输入行内公式使用\\(公式\\) ...

  3. Spring MVC @ResponseBody响应中文乱码

    问题:在前端通过get请求服务端返回String类型的服务时,会出现中文乱码问题 原因:由于spring默认对String类型的返回的编码采用的是 StringHttpMessageConverter ...

  4. Cocos2d-x 3.2 Lua演示样例CurrentLanguageTest(当前语言环境)

    Cocos2d-x 3.2 Lua演示样例CurrentLanguageTest(当前语言环境) 转载请注明:IT_xiao小巫 本篇博客介绍Cocos2d-x 3.2给我们提供的一个样例.获取当前程 ...

  5. Oracle常用SQL与练习

    基本 数学函数 rownum相关 分页查询 (假设每页显示10条) 不包含排序: 包含排序: 时间处理 1. to_char和to_date基本使用 eg1: eg2: 2)months_betwee ...

  6. GrideView(二)---删除功能

    情景一. 没有外键关联, 操作:在数据源中将删除选项选中--- GrideView 中的删除 选项选中 即可情景二. 有外键关联 *RowDeleting 行删除前触发 *RowDeleted 行删除 ...

  7. YTU 2913: 距离产生美

    2913: 距离产生美 时间限制: 1 Sec  内存限制: 128 MB 提交: 152  解决: 133 题目描述 小明和静静是大学同学,毕业后要去两个不同的城市工作.小明要静静做他的女朋友,静静 ...

  8. hdu-4118 Holiday's Accommodation(树形dp+树的重心)

    题目链接: Holiday's Accommodation Time Limit: 8000/4000 MS (Java/Others)     Memory Limit: 200000/200000 ...

  9. Ubuntu Nginx uwsgi django 初试

    /************************************************************************************** * Ubuntu Ngi ...

  10. Watir: 右键点击实例(某些如果应用AutoIt来做会更加简单高效)

    require 'watir' module Watir class Element def top_edge assert_exists assert_enabled ole_object.getB ...