• DLL动态链接库的导入导出



    动态链接库英文DLL,是Dynamic Link Libarary的缩写。
    Dll中包含若干公用的代码、数据等,可供其他模块(DLL或exe文件等)使用。
    Dll中并不是所有的函数都必须供其他模块使用,只有经过 导出(export) 后才允许被外部正常调用。
    动态库的由来:
    Dll最初用于节约应用程序所需要的磁盘空间和内存空间。早前在传统的非共享库中,一部分代码简单的附加到调用的程序中。如果两个程序同时调用同一个子程序,就会出现两份代码。

    动态链接库导出

    创建一个动态链接库的项目:
    在这里插入图片描述


    显式导出

    格式:

    extern "C" _declspec(dllexport) function
    
    • 1

    导出实现:

    /*
    dllmain.cpp  
    */
    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "pch.h"
    
    /*
    在此写上函数的定义及实现
    */
    int sum(int a, int b)
    {
        printf("sum");
        return 0;
    }
    int Div(int a, int b)
    {
        printf("div");
    
        return 0;
    }
    int mul(int a, int b)
    {
        printf("mul");
    
        return 0;
    }
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    /*
    pch.h  在此显式导出Dll
    */
    extern "C" _declspec(dllexport) 
    	int sum(int a, int b);
    extern "C" _declspec(dllexport)
    	int Div(int a, int b);
    extern "C" _declspec(dllexport)
    	int mul(int a, int b);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们在一个主函数DllMain中将函数实现好,然后再从头文件中将函数利用extern ”C“导出

    除了导出函数外,dll文件还可以导出变量,c++类。


    隐式导出

    我们无需使用extern ”C“导出,只需要创建一个新的名为export.def 的文件,然后在此文件中写上如下内容:

    /*
    export.def 文件
    */
    LIBRARY "MyDll"
    EXPORTS
    sum @ 1	//函数名 @符号 函数的序号
    Div @ 2
    mul @ 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • LIBRARY后面跟的是这个项目的名称!!
    • EXPORTS,LIBRARY都是固定的格式
    • 后面跟着导出函数的信息: 函数名 @ 你想指定的函数序号

    注意:需要打开 项目–>属性–>链接器–>输入–>模块定义文件
    然后把export.def 写进去。
    在这里插入图片描述
    表明依靠指定的模块即export.def,导出Dll动态库。


    对于dll项目:编译器通常会产生两个文件,分别是.DLL .lib

    • dll是动态链接库,保存了所有的代码和数据。
    • lib是导入库,保存了一些符号和地址的对应信息。不能单独使用 必须与dll共存。,用于动态链接库的隐式链接。

    动态链接库导入

    显式导入

    显示链接方式调用导出函数:

    	 //加载dll动态库
        HMODULE hModule = LoadLibraryW(L"mydll.dll");
        //获取相应的函数
        GetProcAddress(hModule,"");
        FreeLibrary();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    导入:

    #include "main.h"
    typedef int (*sum)(int a, int b);
    typedef int (*Div)(int a, int b);
    typedef int (*mul)(int a, int b);
    int main()
    {
    	
    	//1. 载入DLL文件
    	HMODULE hModule =  LoadLibraryW(L"MyDll.dll");
    	//2. 拿到要调用的函数
    	sum sumFunc;
    	Div DivFunc;
    	mul mulFunc;
    	if (hModule)
    	{
    		sumFunc = (sum)GetProcAddress(hModule, "sum");
    		printf("%d\n", sumFunc(1, 2));
    		DivFunc = (Div)GetProcAddress(hModule, "Div");
    		printf("%d\n", DivFunc(1, 2));
    		mulFunc = (mul)GetProcAddress(hModule, "mul");
    		printf("%d\n", mulFunc(1, 2));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    注意:

    • LoadLibrary 函数会加载DLL,并且返回一个HMODULE
    • GetProcAddress函数会获得指定的函数,第一个参数为获得的HMUODULE,第二个参数为函数的名字,带“” 号。
    • GetProcAddress的返回值为指定函数的指针,我们需要首先声明某个类型的函数指针,然后将此作为函数的返回值。

    运行如下:
    在这里插入图片描述


    隐式导入

    通过隐式链接的方式调dll导出的函数:

    #pragma comment(lib,"xx.lib")
    
    • 1

    隐式导入:

    /*
    head文件
    */
    #include 
    #include 
    #pragma comment(lib,"MyDll.lib")
    extern "C" _declspec(dllimport)
    	int sum(int, int); 
    extern "C" _declspec(dllimport)
    	int mul(int, int);
    extern "C" _declspec(dllimport)
    	int Div(int, int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    主函数:

    int main()
    {
    	printf("%d\n", mul(1, 2));
    	printf("%d\n", Div(1, 2));
    	printf("%d\n", sum(1, 2));
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行如下:
    在这里插入图片描述

    隐式导出和显式导出,隐式导入和显式导入,我们都可以混合使用!!

  • 相关阅读:
    34.Python面向对象(七)【单例模式&Enum枚举类】
    9、SpringMVC处理ajax请求
    Codeforces Round #724 (Div. 2) C. Diluc and Kaeya
    Faster R-CNN pytorch版
    五年制专转本备考中如何进行有效的自我管理
    SELinux
    【MySQL事务篇】多版本并发控制(MVCC)
    在线Web页面测试工具-WebPageTest
    5- 进入docker 打包的文件,查看内部文件
    HashMap 的 7 种遍历方式与性能分析
  • 原文地址:https://blog.csdn.net/jj6666djdbbd/article/details/127417906