C++下的DLL编程入门
2019独角兽企业重金招聘Python工程师标准>>>
一、 编写第一个入门级dll文件
1. 新建一个dlltest的dll工程,加入一源文件dlltest.cpp,包含add和subtract两个函数如下:
_declspec(dllexport) int add(int a,int b)
{return a+b;
}_declspec(dllexport) int subtract(int a,int b)
{return a-b;
}
注意:
在函数名前加上_declspec(dllexport),这样编译后在连接的时候才会生成dlltest.lib(引入库文件)和dlltest.exp(输出库文件),并且在命令提示符下用dumpbin命令可以看到导出了哪些函数。
方法:在命令提示符下,转到dll文件所在目录下,输入dumpbin –exports dlltest.dll,列出导出函数如下:
这里注意到函数名字已经被改成了?add@@YAHHH@Z ,这种现象叫做名字粉碎,是为了支持函数重载而做的。
2.编写一个基于对话框的MFC程序测试DLL,工程名为calldll,放置两个按纽add和subtract,响应按纽消息,调用这个DLL的add和subtract函数。
先添加响应按钮消息的函数OnAdd和OnSubtract,然后在函数所在源文件中写完整函数体如下:
//extern int add(int,int);
//extern int subtract(int,int);
_declspec(dllimport) int add(int,int);
_declspec(dllimport) int subtract(int,int);void CCalldllDlg::OnAdd()
{// TODO: Add your control notification handler code hereCString str;str.Format("2+3=%d",add(2,3));MessageBox(str);
}void CCalldllDlg::OnSubtract()
{// TODO: Add your control notification handler code hereCString str;str.Format("3-2=%d",subtract(3,2));MessageBox(str);
}
这里采用隐式链接的方式加载动态链接库:
注意:要用关键字extern先声明这两个函数,表明这两个函数是在外部定义的(不过程序中将它注释掉了)。最好是用_declspec(dllimport)表明函数是从动态链接库的lib文件中引入的,这样效率更高。
将文件dlltest.lib拷贝到此工程目录下,并在Project Settings的Link标签下添加此文件:(否则编译会成功,但连接时会出错提示找不到函数的定义)
编译连接生成calldll.exe,这时用Dumpbin -importscalldll.exe查看它的输入信息,可以看到它加载了dlltest.dll。
运行calldll.exe(要成功运行还需将dlltest.dll拷贝到工程目录或此exe所在目录下)
这样,最简单的第一个dll就完成了。
二、 编写涉及到类和头文件的dll文件
1. 新建一个dlltest的dll工程,加入一头文件dlltest.h和一源文件dlltest.cpp。
dlltest.h:
#ifdef DLL_API
#else
#define DLL_API _declspec(dllimport)
#endifDLL_API int add(int,int);
DLL_API int subtract(int,int);class DLL_API Point1 //将整个类导出
{
public:void output(int x,int y);void output1(int x,int y);
};class Point2
{
public:DLL_API void output(int x,int y); //仅导出类中的一个函数void output1(int x,int y);
};
dlltest.cpp:
#define DLL_API _declspec(dllexport)
#include "dlltest.h"
#include <windows.h>
#include <stdio.h>int add(int a,int b)
{return a+b;
}int subtract(int a,int b)
{return a-b;
}void Point1::output(int x,int y)
{HWND hwnd=GetForegroundWindow();HDC hdc=GetDC(hwnd);char buf[50];memset(buf,0,50);sprintf(buf,"x=%d,y=%d",x,y);TextOut(hdc,0,0,buf,strlen(buf));
}void Point1::output1(int x,int y)
{HWND hwnd=GetForegroundWindow();HDC hdc=GetDC(hwnd);char buf[50];memset(buf,0,50);sprintf(buf,"x=%d,y=%d",x,y);TextOut(hdc,0,0,buf,strlen(buf));
}void Point2::output(int x,int y)
{HWND hwnd=GetForegroundWindow();HDC hdc=GetDC(hwnd);char buf[50];memset(buf,0,50);sprintf(buf,"x=%d,y=%d",x,y);TextOut(hdc,0,20,buf,strlen(buf));
}void Point2::output1(int x,int y)
{HWND hwnd=GetForegroundWindow();HDC hdc=GetDC(hwnd);char buf[50];memset(buf,0,50);sprintf(buf,"x=%d,y=%d",x,y);TextOut(hdc,0,20,buf,strlen(buf));
}
2. 编写一个基于对话框的MFC程序测试DLL,此时在工程中包含上面这个头文件,不用在声明导入的类和函数了。
三、 使用模块定义文件和动态加载动态链接库
1. 新建dlltest.dll工程,加入一源文件dlltest.cpp,包含add和subtract两个函数如下:
int add(int a,int b)
{return a+b;
}int subtract(int a,int b)
{return a-b;
}
2. 使用模块定义文件防止文件名改变,在目录中新建dlltest.def文件,增加到工程。
LIBRARY dlltest
EXPORTS
add
subtract
注:LIBRARY和EXPORTS的用法参照MSDN.
3. 编译后用dumpbin查看到函数名没有改变。
4. 用动态加载的方法来调用dll文件。
void CCalldllDlg::OnAdd()
{// TODO: Add your control notification handler code hereHINSTANCE hInst;hInst=LoadLibrary("dlltest.dll");typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"?add@@YAHHH@Z");//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");if(!Add){MessageBox("获取函数地址失败!");return;}CString str;str.Format("2+3=%d",Add(2,3));MessageBox(str);FreeLibrary(hInst);
}
注意:
1. 这里调用的GetProcAddress函数中的第二个参数是动态链接库中导出的函数名,如果动态链接库中没有用模块定义文件防止函数名粉碎,则要用注释掉的GetProcAddress(hInst,"?add@@YAHHH@Z "),另外也可按序号访问GetProcAddress(hInst,MAKEINTRESOURCE(1))。
2. 使用模块定义文件后,如果改变调用约定为_stdcall,函数名也不会被改变,但如果加上_stdcall定义函数,调用时也需要加上_stdcall,否则会出错。
3. 动态加载不需要将文件dlltest.lib拷贝到此工程目录下,并在Project Settings的Link标签下添加此文件,只需将dll文件拷贝到工程目录下即可,并且通过dumpbin -imports calldll.exe查看它的输入信息时,可以看到它并没有加载dlltest.dll。
4. 动态加载的好处是需要时再加载,可以提高执行的效率。当不使用DLL时,调用FreeLibrary减少DLL的使用计数,释放DLL资源,减少系统负担。
5. 不使用模块定义文件,也可用extern "C"使函数名保持不变,如#define DLL1_API extern "C" _declspec(dllexport),但它只能导出全局函数,不能导出类的成员函数,并且如果调用约定被改成了别的方式,此时函数名也被改变,所以一般不用这种方式。
转载于:https://my.oschina.net/leixiaohua1020/blog/302023
C++下的DLL编程入门相关推荐
- linux c语言 ppt,linux操作系统下c语言编程入门.ppt
linux操作系统下c语言编程入门.ppt Linux操作系统下C语言编程入门 CNT Linux操作系统简介基础知识进程介绍文件操作时间概念消息管理线程操作网络编程Linux下C开发工具介绍 一 L ...
- Windows XP下Service的编程入门[2]
Windows XP下Service的编程入门[2] // _dse.cpp : Defines the entry point for the console application. // 作者: ...
- Windows XP下Service的编程入门[1]
Windows XP下Service的编程入门[1] // _dse.cpp : Defines the entry point for the console application. // 作者: ...
- Win32环境下动态链接库(DLL)编程原理
Win32环境下动态链接库(DLL)编程原理 比较大应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作.其中可能存在一些模块的功能较为通用,在构造其它软件系 ...
- linux操作系统下 c语言编程入门
linux操作系统下 c语言编程入门 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门 ...
- linux操作系统下c语言编程入门
linux操作系统下c语言编程入门 整理编写:007xiong 原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux ...
- 【转贴】linux操作系统下c语言编程入门
[转贴]linux操作系统下c语言编程入门 发信人: Lerry (驴是的念来过倒·杏红等头墙上爬), 信区: Linux 标 题: linux操作系统下c语言编程入门 发信站: 哈工大紫丁香 (Fr ...
- linux c++编程教程,Linux下的C++编程入门教程.ppt
<Linux下的C++编程入门教程.ppt>由会员分享,可在线阅读,更多相关<Linux下的C++编程入门教程.ppt(14页珍藏版)>请在人人文库网上搜索. 1.Linux下 ...
- c语言编程操作系统,操作系统下c语言编程入门.doc
操作系统下c语言编程入门 linux操作系统下c语言编程入门 1)Linux程序设计入门--基础知识? 2)Linux程序设计入门--进程介绍? 3)Linux程序设计入门--文件操作? 4)Linu ...
最新文章
- CodeForces 66C 	Petya and File System (实现)
- 在外企必会的10个英文单词 (Ten words you must mastered for foreign company employee)
- StringBuffer与StringBuilder的区别
- TensorFlow莫烦 placehoder (三)
- mysql 主表存hash和子表的名字_【mysql】mysql分表和表分区详解
- Vijos——T 1016 北京2008的挂钟 || 洛谷—— P1213 时钟
- SparkStreaming安全消费Kafka数据
- IAR8.3 STM8安装过程
- pad平板性能测试软件,苹果iPad 2020款评测,最便宜的iPad,性能碾压安卓?
- 超大背包问题(01背包)
- EPOCH, BATCH, INTERATION
- endl和\n的区别
- 两个时间之间的有多少个工作日,有多少天,有多少天的周末
- 自动擦地机器人需要怎么留电_irobot擦地机器人是否好用,需要和扫地机器人配合么?...
- 永恒之蓝漏洞攻击完整步骤
- 如何做番茄炖牛腩——hadoop理解
- 华为云服务器(Centos7)安装与卸载mysql8
- 书写函数:求棋盘上芝麻重量
- Unity创建和修改本地Word文档
- UIQ3.0模拟器上网和显示中文
热门文章
- 计算机汉字救亡运动简史丨视频
- 中国物流供应链“零的突破”!阿里路径规划算法入围运筹学“奥斯卡”
- 我从GitHub上看到了编程语言八年变迁史 | Reddit 30.7k
- 我从哆啦A梦的口袋里,掏出一辆充气电动车
- 倒下的RoadStar结局来了:VC清盘止损,三位创业者承担1亿债务,打着官司各投林...
- Numpy中的random模块中的seed方法的作用
- HTTP.sys 远程执行代码验证工具
- 性能分析:hash索引导致delete慢
- ExtJS-Grid框增加复选框checkbox
- MKTickerView