VC++ 2017 动态链接库的创建和使用总结
- 格式:docx
- 大小:288.42 KB
- 文档页数:4
vc调用动态库dll和lib由于我们经常要调用一些第三方厂商或其他编译器编写的动态链接库,但是一般都不提供源文件或.lib文件,而作为VC隐式链接到DLL(implicitlylinktotheDLL)调用,这些却是必需的。
本文将主要讨论在没有源文件及.lib输入库文件或欲调用Windows未公开函数的情况下重建.Lib文件的方法。
在建立之前,我们首先要了解一下DLL 输出函数的几种方式。
一、从DLL中输出函数的方式(callingconventions)_cdecl是C和C 程序的缺省调用方式。
每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。
函数采用从右到左的压栈方式。
VC将函数编译后会在函数名前面加上下划线前缀。
_stdcall是Pascal程序的缺省调用方式,通常用于Win32Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。
VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。
_fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。
用VC建立一个空的动态链接库,并加入以下三个文件://noname.h动态链接库头文件extern"C"void_stdcallstdcallproc(void);extern"C"void_cdeclcdeclproc(void);extern"C"void_fastcallfastcallproc(void);//noname.cpp动态链接库实现文件#includeextern"C"void_stdcallstdcallproc(void){MessageBox(0,"stdcallfunction","dllcall",0);}extern"C"void_cdeclcdeclproc(void){MessageBox(0,"cdeclfunction","dllcall",0);}extern"C"void_fastcallfastcallproc(void){MessageBox(0,"fastcallfunction","dllcall",0);}//noname.def动态链接库输出函数定义LIBRARY"noname"EXPORTSstdcallproc@1nonamecdeclproc@2fastcallproc@3编译后生成noname.lib,输出函数_cdeclproc,_stdcallproc@0,@fastcallproc@0;生成的noname.dll在Exescope等PE格式的工具中只能看到cdeclproc和fastcallproc函数,因为stdcallproc被指定noname属性,没有名字输出,类似于Windows未公开函数。
1.新建MFC DLL工程,取名为:DLL0410
动态链接库的创建和调用(类,函数的DLL导出和调用)
2.在工程中编辑好DLL0410.h,DLL0410.cpp,DLL0410.def三个文件后编译生成对应的dll和lib文件
2.1 DLL0410.h
2.2 DLL0410.cpp
2.3 DLL0410.def
2.4 编辑好上面的3个文件编译后,用dumpbin命令查看是否有函数导出。
(如图所示,sub全局函数和add类的成员函数已经导出)
3.新建一个工程DLL0410test将生成的DLL0410.dll,DLL0410.lib以及DLL0410.h文件拷贝到 DLL0410test工程目录下
4.静态调用:在工程的DLL0410test.cpp文件中导入头文件DLL0410.h,并编写对应的静态调用代码。
同时也要在工程属性链接中加入DLL0410.lib文件。
(如果编译出错有可能是,工程属性中的常规>>字符集>>修改为 使用多字节字符集)
运行成功
5.4.动态调用:只需将生成的DLL0410.dll文件拷贝到新建工程目录下,直接在工程的
DLL0410test.cpp中编写动态调用代码即可。
不用做其他任何连接和导入头文件的操作。
运行成功。
[动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
DLL 还有助于共享数据和资源。
多个应用程序可同时访问内存中单个DLL 副本的内容。
动态链接库(Dynamic Link Library或者Dynamic-link library,缩写为DLL),是微软公司在微软视窗操作系统(即Windows操作系统)中实现共享函数库概念的一种方式。
这些库函数的扩展名是.DLL、.OCX(包含ActiveX控制的库)或者.DRV(旧式的系统驱动程序)。
动态链接库缩写为DLL,在电脑中可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。
例如,您有一个大型网络游戏,如果把整个数百MB 甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库(DLL)中,您无需重新生成或安装整个程序就可以应用更新。
]1.使用VC6.0 生成DLL新建项目“Win32 Dynamic-Link Library”,输入项目名称,确定后选择“A simple DLL project”点击“完成”。
以下为cpp文件自动生成的代码:#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){return TRUE;}编辑cpp文件:在#include "stdafx.h"的下一行加入extern "C" __declspec(dllexport) int fun(int a, int b);/*这是C格式导出函数;这种写法一般用在C++写的DLL中,指按C的规则导出这个函数,否则导出的函数会很怪; 加上extern "C" 表示按标准C格式导出函数.如果去掉仅兼容C++;其中int fun(int a, int b) 这部分代码是我们想用dll 实现的函数原型声明如果还想加入其他的可以继续加入extern "C" __declspec(dllexport) int fun1(int a, int b);*/DllMain 是DLL 的默认入口函数,类似于C语言的main函数,该例子无需修改此处,在DllMain 的后面加入:int fun(int a,int b){return a+b;}这就是我们想用DLL 实现的函数的定义,build 之后就会在debug 目录下生成我们想要的dll 文件2.调用DLL新建一个Win32 Console Application 工程,把刚才生成的dll 文件拷贝到工程的根目录下在stdafx.h 文件中加入:#include <windows.h>编辑cpp文件:#include "stdafx.h"typedef int (*PFUN)(int,int);void main(){HMODULE hModule = ::LoadLibrary("dlltest.dll");PFUN newfun = (PFUN)::GetProcAddress(hModule,"fun");int i = newfun(1,2);printf("The result is %d\n",i);::FreeLibrary(hModule);}然后,运行就可以看到结果了转VC6.0下调用Dll文件提供的函数接口和全局变量函数接口:首先把生成的Dll文件(如RegularDll.dll和RegularDll.lib)拷贝到当前工程所在文件夹,调用有两种方法:1)动态方法:使用LoadLibrary和GetProcAddress等函数,例typedef void (*lpFun)(void);HINSTANCE hDll;hDll = LoadLibrary("RegularDll.dll");if (NULL==hDll) {MessageBox("Dll load failed!");}lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");if (NULL == pShowDlg) {MessageBox("Load function \"ShowDlg\" failed!");}pShowDlg();*/2)静态声明方法:创建Dll的工程中,函数声明和定义时用_stdcall 修饰,例void _stdcall ShowDlg(void){...}在调用dll的工程的文件中,在文件头部声明库和函数,如下例#pragma comment(lib,"RegularDll.lib")void _stdcall ShowDlg(void);调用时直接ShowDlg()就可以了。
使用vs建立动态链接库dll的过程和使用方法创建动态链接库(DLL)的过程可以分为几个步骤。
我将使用Visual Studio 来演示这个过程:创建DLL的步骤:1.打开Visual Studio,选择“文件”->“新建”->“项目”。
2.在新项目窗口中,选择“Visual C++”->“Windows桌面向导应用程序”。
3.输入项目名称和位置,然后点击“确定”。
4.在“解决方案资源管理器”中,右键单击项目名称->添加->新建项。
5.在“添加新项”窗口中,选择“DLL”,输入DLL名称,然后点击“添加”。
编写DLL代码:现在你已经有了一个空的DLL,你可以开始编写你的代码了。
例如,你可以添加以下代码到你的.cpp文件中:在这个例子中,我们创建了一个简单的函数add,它接收两个整数并返回它们的和。
extern "C"部分告诉编译器使用C链接规则创建导出函数,__declspec(dllexport)部分使得该函数可以从DLL中导出。
编译和生成DLL:在Visual Studio中,你可以通过点击“生成”菜单然后选择“生成解决方案”来编译和生成你的DLL。
如果编译成功,你可以在你的项目文件夹的Debug或Release 文件夹中找到生成的DLL文件。
使用DLL:使用DLL的过程可以分为几个步骤:1.加载DLL:使用Windows API函数LoadLibrary可以加载DLL。
例如:HMODULE hMod = LoadLibrary(TEXT("MyDLL.dll"));。
这个函数会返回一个模块句柄,如果DLL加载成功的话。
2.获取函数地址:使用GetProcAddress函数可以获取DLL中函数的地址。
例如:add_proc = (int (*)(int, int))GetProcAddress(hMod, "add");。
DLL的创建与调用1、DLL的概念DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。
这些可以直接拿来使用。
静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式。
静态链接库把最后的指令都包含在最终生成的EXE 文件中了;动态链接库不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
(2)静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
动态链接库的分类:Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
非MFC动态库不采用MFC 类库结构,其导出函数为标准的C接口,能被非MFC或MFC编写的应用程序所调用;MFC规则DLL 包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写的应用程序所调用。
2、创建一个DLL2.1 非MFC的DLL2.1.1声明导出函数:extern “C” __declspec(dllexport) int add(int a, int b);其中extern “C”为声明为C编译。
由于C++编译器在编译的时候会造成其函数名的该变,在其他应用程序中导致函数不可调用,而C编译器则不会在编译后改变其函数名。
这样如果用C编译的程序来调用该dll中的函数时,可能会造成找不到该函数。
__declspec(dllexport)表示该函数为DLL输出函数,即其他应用程序可以调用该函数从dll中声明输出函数有两种方式:(1)另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
如何用VC创建及调用DLL使用Visual C++(VC++)创建和调用动态链接库(DLL)可以提供一种模块化的方式来组织和重用代码。
本文将介绍如何使用VC++创建DLL,并在另一个VC++项目中调用该DLL。
创建DLL以下是使用VC++创建DLL的步骤:1.打开VC++,在“文件”菜单中选择“新建”->“项目”。
2. 在“新建项目”对话框中,选择“Win32控制台应用程序”。
点击“下一步”。
3.输入项目名称,并选择项目位置,点击“下一步”。
4.在“应用程序类型”对话框中,选择“DLL”并取消勾选“预编译头”。
点击“下一步”。
5.在“进入代码”对话框中,选择“空项目”。
点击“完成”。
6. 创建一个新的源文件,例如“MyDLL.cpp”。
7. 在“MyDLL.cpp”中,编写所需的函数并导出。
例如:```C++#include <Windows.h>// 导出的函数需要使用__declspec(dllexport)修饰extern "C" __declspec(dllexport) int AddNumbers(int a, int b) return a + b;```8. 在项目属性中,选择“链接器”->“高级”,将“入口点”设置为“DllMain”。
9.在“生成”菜单中选择“生成解决方案”,以生成DLL文件。
以下是在VC++项目中调用DLL的步骤:1.打开VC++,在“文件”菜单中选择“新建”->“项目”。
2. 在“新建项目”对话框中,选择“Win32控制台应用程序”。
点击“下一步”。
3.输入项目名称,并选择项目位置,点击“下一步”。
4.在“应用程序类型”对话框中,选择“控制台应用程序”并取消勾选“预编译头”。
点击“下一步”。
5.在“附加选项”对话框中,勾选“空项目”。
点击“完成”。
6.将之前生成的DLL文件复制到新项目的文件夹中。
7.在项目属性中,选择“C/C++”->“常规”,将“附加包含目录”设置为包含DLL文件的文件夹路径。
动态库的使用方法
动态库(Dynamic Link Library,DLL)是一种包含可在多个程序中共享的代码和数据的文件格式。
动态库的使用方法如下:
1. 链接库文件:将动态库文件与源代码进行链接,以便使用其中的函数和数据。
在编译时,可以将库文件的路径添加到链接器的搜索路径中,并将库文件的名称添加到链接器的命令行参数中。
2. 导入函数:在程序中声明需要使用的库函数。
可以通过包含相应的头文件来获取函数的声明。
在编译时,链接器将使用库文件中的函数实现替换这些声明,以便在程序中调用它们。
3. 运行时加载库:在程序运行时,通过调用操作系统提供的加载库函数来加载动态库。
可以使用操作系统提供的加载函数,如LoadLibrary(Windows)或dlopen(Linux)。
加载库时,可以指定库文件的路径,并获取一个句柄或指针,以便后续使用。
4. 使用库函数:一旦库文件加载完成,在程序中就可以使用库函数了。
可以通过句柄或指针来调用库函数,并传递所需的参数。
库函数的执行结果将返回给程序进行处理。
5. 卸载库:在程序不再需要使用动态库时,可以调用操作系统提供的卸载库函数,如FreeLibrary(Windows)或dlclose (Linux),以释放库文件所占用的资源。
需要注意的是,动态库的使用方法可能会因操作系统和开发环境的不同而有所差异。
因此,在使用动态库时,最好根据具体的环境和要求进行相应的调整和配置。
在VC中创建DLL文件的方法步骤今天教大家在VC中创建DLL文件的方法步骤,一起来学习一下,并不是很难的,相信聪明的你一看就会。
一.Win32动态链接库1.制作的步骤:(1)新建WIN32 Dynamic-link Library工程,工程名为MyDll,选择A simple DLL project类型。
(2)MyDll.h的内容如下:(3)MyDll.cpp的内容如下:2.使用方法:(1).隐式调用法:将MyDll.lib和MyDll.h拷贝到需要应用该DLL 的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行:(2).显示调用法:将MyDll.lib和MyDll.h拷贝到需要应用该DLL 的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中包含头文件,如:同时还需要在Project->Setting->Link->Object/library modules的框中增加MyDll.lib这个库。
二.MFC动态链接库1.制作的步骤:(1)新建MFC AppWizard(dll)工程,工程名为MFCDll,选择Regular DLL using shared MFC DLL类型。
(2)在生成的MFCDll.cpp文件后面增加下面几行:(3)在生成的MFCDll.def文件后面增加如下:(4)编译后会产生两个文件MFCDll.lib,MFCDll.dll2.使用方法(1)隐式调用法:将MFCDll.lib拷贝到需要应用该DLL的工程的目录下,将MyDll.dll拷贝到产生的应用程序的目录下,并在需要应用该DLL中的函数的CPP文件中添加如下几行://注意这里没有在MFCDll.h中声明函数,所以不能直接包含MFCDll.h来声明函数。
//当然如果你的DLL中有很多函数,那可以另外写个MFCDll.h,包含所有的函数声明,然后直接将头文件包含进去(2)显示调用法:与Win32的调用方法一样,不需要#pragma comment(lib,"MFCDll");,但是需要在Project->Setting->Link->Object/library modules的框中增加MFCDll.lib这个库。
vs编译动态库的配置方法VS编译动态库的配置方法动态库(Dynamic Link Library,简称DLL)是一种包含可被其他程序调用的代码和数据的文件类型。
与静态库相比,动态库可以在运行时加载和卸载,使得程序的开发和维护更加灵活方便。
在使用Visual Studio(VS)进行开发过程中,配置和编译动态库是一个非常常见的任务。
本文将一步一步回答如何在VS中配置和编译动态库的问题。
第一步:新建解决方案和项目1. 启动Visual Studio,选择“文件”→“新建”→“项目”。
2. 在左侧的“模板”中,选择“Visual C++”→“Win32”→“Win32控制台应用程序”。
输入项目名称并选择保存路径,然后点击“确定”。
3. 在“Win32应用向导”中,选择“下一步”。
4. 在“应用程序类型”对话框中,选择“Dll”(动态链接库),然后点击“下一步”。
5. 在“附加选项”对话框中,根据需要选择或取消选中一些选项,然后点击“下一步”。
6. 在“Win32应用向导”的最后一个对话框中,点击“完成”以创建项目。
第二步:配置项目属性1. 右键单击解决方案资源管理器中的项目名称,选择“属性”。
2. 在“常规”选项卡中,确认“配置类型”为“动态库(.dll)”,如果不是,选择该选项。
3. 在“常规”选项卡中,根据需要,将“目标框架”设置为对应的.NET 版本。
4. 在右侧面板中,点击“DLL导出”。
5. 在“DLL导出”对话框中,将需要导出的函数写入“函数列表”中,并为每个函数指定导出名称。
这些函数将被其他程序调用。
6. 在“常规”选项卡中,检查“附加包含目录”和“附加库目录”的设置,确保项目依赖的头文件和库文件路径正确。
7. 在“链接器”→“输入”选项卡中,检查“附加依赖项”和“输出文件”设置,确保项目依赖的库文件正确。
8. 在“生成事件”选项卡中,根据需要添加自定义生成事件,例如在编译完成后自动复制动态库文件到指定路径。
Visual studio c++ 2017 动态链接库的创建和使用总结
一动态链接库的创建两种方式:
1、只有从文件->新建->项目->Windows桌面-> Windows桌面向导->选择“动态链接
库(.dll)->生成解决方案,才会生成.dll和.lib文件。
(1)在头文件声明中(注意要在头文件变量和函数声明中,而不是在变量和函数的定义中声明),不加extern “C”修饰,编译成DLL后,用depends.exe查看导出函数名。
可以看出,导出的函数名都被编译器篡改了。
(2)在头文件声明中,变量和函数名前加extern “C”修饰后,编译成DLL后,再用depends.exe查看导出函数名。
可以看出,用extern “C”修饰的函数名,编译后函数名保持不变。
类及成员函数不能用extern “C”修饰,编译成DLL后,成员函数名发生了改变。
2、如果从文件->新建->项目->动态链接库(DLL)->生成解决方案,就只生成.dll,不生成.lib。
二动态链接库的调用两种方式:
1、显式调用
(1)使用显式调用的前提:创建的DLL,编译时不要篡改函数名称,定义函数名时,可用extern “C”修饰函数名,保证编译时,函数名不被篡改。
否则GetProcAddress( )不能正确地获取dll中的函数名。
但是导出的类不能使用extern “C”修饰。
(2)使用显式调用的优点:不用动态链接库的.h和.lib文件,只要有.dll文件就可调用库函数,使用LoadLibrary(),在需要调用.dll中的库函数时,才动态加载到内存中,使用完毕后,可以用FreeLibrary()释放内存中的dll;使用GetProcAddress( )获取dll中的函数名。
必须事先知道dll中的函数名和形式参数。
(3)使用显式调用缺点:调用每个函数时,都必须使用 GetProcAddress( )获取dll中的函数名,并转换成原来的函数,比较麻烦。
而隐式调用DLL函数,由于使用了DLL的头文件.h,使用起来非常方便。
2、隐式调用
(1)隐式调用DLL函数缺点:
应用程序加载时,在内存中载入DLL动用库中的函数、变量、或类。
使用完毕后,DLL 也不会从内存中释放。
.lib包含了库函数的入口,但不包含函数代码,应用程序调用时,才从dll中载入。
(2)隐式调用DLL函数优点:
应用程序调用dll时,需要.lib和.h文件,在应用程序.exe文件夹debug或者release 中有DLL文件,即.h、.lib和.dll三个文件,在应用程序中直接使用DLL中的类和函数,可以不考虑编译DLL函数和变量名发生改变的问题。
不需要像显式调用那样,函数需要
用 GetProcAddress( )一一获取。
隐式调用DLL中的变量、函数和类,有两种方法:
(1)在主程序中包含DLL的头文件dll.h,在main( )前加上#pragma
comment(lib,”dll.lib”),没有分号,再在debug或release中复制DLL.dll。
(2)在主程序中包含DLL的头文件dll.h,在项目属性->链接器->添加依赖项中加上“dll.lib;“,再在debug或release中复制DLL.dll,即可。
隐式调用DLL中的变量、函数和类,由于使用了DLL头文件声明,调用起来非常方便。
不需要用GetProcAdress( )逐句获取函数名。
使用显式调用LoadLibrary(),只能调用DLL 中的函数,不能调用DLL中类和成员函数。