DLL的创建与使用

一、动态链接库(DLL)

动态链接库提供了一种方法,使进程可以调用不属于其执行代码的函数。函数的可执行代码位于一个.dll文件中,该文件包含一个或多个已被编译、链接并使用它们的进程分开存储的函数。

优点:

1.扩展了 应用程序的特性

2.可以使用多种编程语言来编写

3.简化项目的管理

二、依赖项

当某个程序或DLL使用其他DLL或DLL函数时,就会创建依赖项,因此程序就不会再独立了,依赖项如果被破坏,该程序可能出现问题。

三、入口点

在创建DLL时,可以有选择地指定入口点的函数。当进程或线程将它们自身附加到DLL或者将它们自身以DLL分离时,都会调用入口函数。入口函数应该只进行简单的初始化工作,而不应该调用其他DLL函数或者终止函数。

关于创建DLL,我的环境是VS2017,步骤为:文件->新建项目->选择动态链接库(DLL)->完成。在创建的项目中的源文件可以看到有一个已经创建好的dllmain.cpp,这个就DLL入口点的代码了。

 1 // dllmain.cpp : 定义 DLL 应用程序的入口点。
 2 #include "stdafx.h"
 3 BOOL APIENTRY DllMain( HMODULE hModule,     //模块句柄
 4                        DWORD  ul_reason_for_call,//调用原因
 5                        LPVOID lpReserved   //参数保留,好像没什么用
 6                      )
 7 {
 8     switch (ul_reason_for_call)
 9     {
10     case DLL_PROCESS_ATTACH:  //DLL被某个程序加载
11     case DLL_THREAD_ATTACH:   //DLL被某个线程加载
12     case DLL_THREAD_DETACH:   //DLL被某个线程卸载
13     case DLL_PROCESS_DETACH:  //DLL被某个程序加载
14         break;
15     }
16     return TRUE;
17 }

四、如何导出(在DLL中实现的)

第一种:

步骤1:向所有需要导出的DLL函数中添加关键字__declspec(dllexport)。

步骤2:要在应用程序中使用导出的DLL函数,必须使用__declspec(dllexport)来声明要导入的各个函数。

本章使用的就是这种方法

通常最好使用一个包含define语句和ifdef语句的头文件,以便分隔导出语句和导入语句,代码如下。

说明:该DLL库实现的是简单的加减乘除运算,注意实现减法的这个函数,我这里特别使用了一个抽象类来实现,我发现有些企业代码都会有这种类似的抽象类,然后用纯虚函数做接口。

 1 //__declspec(dllexport)修饰符指示编译器和链接器从
 2 //DLL 导出函数或变量,以便其他应用程序可以使用它,在ExprotDll.h中
 3 #pragma once
 4 #ifdef EXPORTDLL_EXPORTS
 5 #define EXPORTDLL_API __declspec(dllexport)
 6 #else
 7 #define EXPORTDLL_API __declspec(dllimport)
 8 #endif
 9
10 //导出的类
11 class EXPORTDLL_API CExportDll {
12 public:
13     // TODO:  在此添加方法
14     //用纯虚函数做为接口
15     virtual int SUBTARCT(int a, int b) = 0;
16     virtual ~CExportDll() {};
17
18 };
19
20 //导出函数,如果是在C++环境下,则执行"{" "}"中的内容
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24     EXPORTDLL_API CExportDll* Create();
25     EXPORTDLL_API void Destroy(CExportDll* ex);
26 #ifdef __cplusplus
27 }
28 #endif
29
30 //也可用下列方法定义导出函数
31 extern "C" EXPORTDLL_API int nExportDll;
32 extern "C" EXPORTDLL_API int ADD(int a, int b);
33 extern "C" EXPORTDLL_API int MULTIPLY(int a, int b);
34 extern "C" EXPORTDLL_API float DIVIDE(float a, float b);

第二种:

创建模块定义文件.def以列出导出的DLL函数:

五、特别调用

需要注意以下一些情况:

1.如果使用了Win32 API,则应该使用关键字__stdcall修饰函数

2.如果将C++生成的DLL供标准C语言使用,输出文件用extern "C"来修饰,设置导出函数时采用.def文件形式,而不是__declspec(dllexport)

六、编写DLL

创建DLL工程并且定义了相应的导出函数、变量或类之后,接下来就是实现功能了。本章中因为CExportDll是一个抽象类,所以需要再创建一个它的子类(CExportDllChild.h中),实现相应的接口功能(EXportDll.cpp中),同时其他函数也在(EXportDll.cpp)中实现功能。

1 //ExportDllChild.h
2 #pragma once
3 #include "ExportDll.h"
4
5 class CExportDllChild :public CExportDll
6 {
7     virtual int SUBTARCT(int a, int b);
8     virtual ~CExportDllChild() {};
9 };
 1 // ExportDll.cpp : 定义 DLL 应用程序的导出函数。
 2
 3 #include "stdafx.h"
 4 #include "ExportDllChild.h"
 5
 6 //这是一个导出变量的一个示例
 7 EXPORTDLL_API int nExportDll = 0;
 8
 9 //这是导出函数的几个示例
10 //当前使用的是C++编译出来的
11
12 //构造对象
13 EXPORTDLL_API CExportDll* Create()
14 {
15     return new CExportDllChild;
16 }
17 //析构对象
18 EXPORTDLL_API void Destroy(CExportDll* ex)
19 {
20     delete ex;
21 }
22 //加
23 EXPORTDLL_API int ADD(int a, int b)
24 {
25     return a + b;
26 }
27 //减
28 int CExportDllChild::SUBTARCT(int a, int b)
29 {
30     return a - b;
31 }
32 //乘
33 EXPORTDLL_API int MULTIPLY(int a, int b)
34 {
35     return a * b;
36 }
37 //除
38 EXPORTDLL_API float DIVIDE(float a, float b)
39 {
40     if (b != 0) {
41         return a / b;
42     }
43     else
44         return -1;
45 }

创建编写好后,进行生成,可以在项目Debugp目录下看到生成的动态库.dll和静态库.lib

七、调用DLL

调用DLL有两种方法,一种是显式链接方式,另一种是隐式链接方式。

在调用前,先创建一个Win32控制台应用程序或者MFC,这里创建的是一个简单的Win32程序(LoadDll)

1.显式链接:

在此项目中,需要将CExportDllChild.h放在LoadDll目录下。然后在cpp中添加以下代码

 1 // LoadDll.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3
 4 #include "pch.h"
 5 #include <Windows.h>
 6 #include <iostream>
 7 #include "ExportDll.h"
 8
 9 /*-------------动态链接-------------*/
10 int main()
11 {
12     HMODULE hModule;   //模块句柄
13     //定义函数指针
14     typedef int(*FUNC1)(int a, int b);
15     typedef CExportDll* (*CreateFun2)();
16     typedef void(*DestroyFun2)(CExportDll* ex);
17     typedef int(*FUNC3)(int a, int b);
18     typedef float(*FUNC4)(float a, float b);
19     //调用DLL,先找当前文件夹,如果没有,就会去system32下查找
20     hModule = ::LoadLibrary(L"ExportDll.dll");
21
22     if (hModule == NULL){
23         MessageBox(NULL, L"DLL加载失败", L"Mark", MB_OK);
24     }
25     //获取相应DLL函数的入口地址
26     FUNC1 add = (FUNC1)::GetProcAddress(hModule, "ADD");
27     CreateFun2 create = (CreateFun2)::GetProcAddress(hModule, "Create");
28     DestroyFun2 destroy = (DestroyFun2)::GetProcAddress(hModule, "Destroy");
29     FUNC3 multiply = (FUNC3)::GetProcAddress(hModule, "MULTIPLY");
30     FUNC4 divide = (FUNC4)::GetProcAddress(hModule, "DIVIDE");
31     //加
32     if (add != NULL){
33         std::cout << "a+b="<< add(10, 5) << std::endl;
34     }
35     //减
36     if (create&&destroy)
37     {
38         CExportDll* p = create();
39         std::cout << "a-b=" << p->SUBTARCT(10, 5) << std::endl;
40         destroy(p);
41         p = NULL;
42     }
43     //乘
44     if (multiply != NULL){
45         std::cout << "a*b=" << multiply(10, 5) << std::endl;
46     }
47     //除
48     if (divide != NULL)
49     {
50         std::cout << "a/b=" << divide(10, 5) << std::endl;
51     }
52     FreeLibrary(hModule);   //释放句柄
53     return 0;
54 }

调用结果:

2.隐式调用

在程序开始执行时就将DLL文件加载到应用程序中。隐式调用没用过,不做表述了。

原文地址:https://www.cnblogs.com/main404/p/11185127.html

时间: 2024-10-15 07:02:01

DLL的创建与使用的相关文章

Delphi中DLL的创建和使用【转】

Delphi中DLL的创建和使用     1.DLL简介:   2.调用DLL:   3.创建DLL:   4.两个技巧:   5.初始化:   6.例外处理.            1.DLL简介     DLL是Dynamic-Link   Libraries(动态链接库)的缩写,库里面是一些可执行的模块以及资源(如位图.图标等).可以认为DLL和EXE基本上是一回事,只是DLL不能直接执行,而必须由应用程序或者其他DLL调用.DLL为应用程序间的资源共享提供了方便,同时也是多语言混合编程的

C++ dll的创建和使用

在介绍Dll之前先了解下常见三种函数调用约定. 参考:https://www.cnblogs.com/yejianyong/p/7506465.html 我们使用的VS默认使用的函数调用约定是__cdel,而Windows API默认的调用约定是__stdcall.我们在使用一个dll的接口时,一定要确保你使用接口时的调用约定和接口定义时的调用约定一致.因为不同的调用约定,函数的栈内存释放的方式不同. 然后我们再了解下extern C的作用,参考https://www.cnblogs.com/c

C#中调用c++的dll具体创建与调用步骤,亲测有效~

使用的工具是VS2010哦~其他工具暂时还没试过 我新建的工程名是my21dll,所以会生成2个同名文件.接下来需要改动的只有画横线的部分 下面是my21dll.h里面的... 下面的1是自动生成的不用动,或者也可以不要,因为只是一个宏而已下面可以做相应修改. 下面的2是自动生成的类,我没用就注释掉了 下面的3是自动生成的一个测试函数,原来函数最前面是extern,记住精髓是要改成EXTERN_C 下面的4是我自己写的一个测试函数,用来求和 下面是my21dll.cpp里面的 号3对应上面号3的

VS中 DLL的创建及函数导出(参考MSDN)

新建一个DLL工程: 新建 - 项目 - vc++ - win32 - win32控制台应用程序,工程名假设取为 MathFuncsDll 向导中选择DLL,取消预编译头 完成. 此时会有dllmain.cpp, MathFuncsDll.cpp 两个cpp文件及生成的 stdafx.h, targetver.h stdafx.cpp, 后面这三个文件其实是没用的,可以删掉,然后把dllmain.cpp 中的#include "stdafx.h"改成#include <windo

DLL的创建和使用

1 #ifndef MYDLL_H 2 #define MYDLL_H 3 4 #ifdef DLL_IMPLEMENT_ 5 #define DLL_APL __declspec(dllexport) 6 #else 7 #define DLL_API __declspec(dllimport) 8 #endif 9 10 //导出函数接口 11 extern "C" 12 { 13 int DLL_API add(const int &a, const int &b

DLL 的创建及调用,效果及源码

源码地址:http://files.cnblogs.com/tiankaileo/DLL.rar

DLL中创建对话框之加载资源【备忘一】

HINSTANCE hinst = GetModuleHandle(0);        HRSRC hr = ::FindResource(hinst, MAKEINTRESOURCE(IDD_MEMDIALOG), RT_DIALOG);        LoadResource(hinst, hr);        m_hWnd=CreateDialog(hinst, MAKEINTRESOURCE(IDD_MEMDIALOG), 0, DlgProc);

VS2010 C++创建DLL步骤

VS2010中 C++创建DLL图解 一.DLL的创建 创建项目: Win32->Win32项目,名称:MyDLL 选择DLL (D) ->完成. 1.新建头文件testdll.htestdll.h代码如下:#ifndef TestDll_H_#define TestDll_H_#ifdef MYLIBDLL#define MYLIBDLL extern "C" _declspec(dllimport) #else#define MYLIBDLL extern "

delphi 创建DLL文件 及其调用和注意事项

首先创建一个DLL文件,项目自带的代码为: library ProjectPnr; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or fu