• Windows库程序


    Windows库程序

    静态库
    静态库特点
    • 运行不存在 --> 没有入口
    • 静态库源码被链接到调用程序中
    • 目标程序的归档
    C语言静态库
    • C静态库的创建

      1. 创建一个静态库项目
      2. 添加库程序,源文件使用C文件
    • C静态库的使用

      库路径设置: 可以使用pragma关键字设置

      #pragma comment(lib,".../xxx.lib")
      
      • 1
    C++语言静态库
    • C++静态库的创建

      1. 创建一个静态库项目

      2. 添加库程序,源文件使用CPP文件

    • C++静态库的使用

      库路径设置: 可以使用pragma关键字设置

      #pragma comment(lib,".../xxx.lib")
      
      • 1

      C++ 静态库函数使用时必须要有声明

      C++ --> 换名,编译器会给函数换名

      C编译器没有换名

    • C++ 不换名

      extern "C" 函数声明;
      // 使用C方式编译,不换名
      
      • 1
      • 2
    动态库
    动态库特点
    1. 运行时独立存在 --> 可以运行 --> 依附其他程序存在 --> 运行后有自己的地址空间
    2. 源码不会链接到执行程序
    3. 使用时加载( 使用动态库必须是动态库执行 )
    与静态库比较
    1. 由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小

    2. 静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或者地址)未变化,其他使用DLL的程序不需要重新链接

    动态库创建
    • 创建动态库项目

    • 添加库程序

    • 库程序导出 - 提供给使用者库中的函数等信息

      导出的是函数地址

      1. 声明导出

        使用_declspec(dllexport) 导出函数

        动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同

        要使用extern “C” --> 不换名

      2. 模块定义文件 .def

        LIBRARY  动态库文件名->不要.dll后缀
        EXPORTS        // 库导出表
        函数名1   @1    // 导出的函数
        函数名2   @2    // 导出的函数
        函数名n   @n    // 导出的函数
        
        • 1
        • 2
        • 3
        • 4
        • 5

    image-20221114095344954

    动态库的使用
    • 隐式链接( 操作系统负责使用动态库执行)

      1. 头文件和函数原型

        可以在函数声明前,增加_declspes(dllimport)

        _declspes(dllimport) 函数声明;
        
        • 1
      2. 导入动态库的LIB文件

        #pragma comment(lib,"xxx.lib")
        
        • 1
      3. 在程序中使用函数

      4. 隐式链接的情况,dll文件可以存放的路径

        1. 与执行文件同一个目录下
        2. 当前工作目录
        3. Windows目录
        4. Windows/System32目录
        5. Windows/System
        6. 环境变量PATH指定目录
    • 显式链接( 自己负责使动态库执行 )

      1. 定义函数指针类型 typedef

        typedef int (*ADD) (int m,int n);
        
        • 1
      2. 加载动态库

        HMODULE LoadLibrary(
        	LPCTSRT lpFileName   // 动态库文件名或者全路径
        );// 返回DLL的实例句柄 ( HINSTANCE )
        
        • 1
        • 2
        • 3

        让动态库进内存

      3. 获取函数真实地址

        地址值为0 是NULL, 为无效地址

        FARPROC GetProcAddress(
        	HMODULE hModule , // DLL句柄
            LPCTSRT lpProcName, // 函数名称
        ); // 成功返回函数地址
        
        • 1
        • 2
        • 3
        • 4
      4. 使用函数

      5. 卸载动态库

        BOOL FreeLibrary(
        	HMODULE hModule  // DLL的实例句柄
        );
        
        • 1
        • 2
        • 3
    动态库中封装类
    • 在类名称前增加_declspec(dellexport)定义

      class _declspec(dllexport) CMath{
          //...  
          public:
          int Add(int n1,int n2);
          int Sub(int n1,int n2);
      };
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 通常使用预编译开关切换类的导入导出定义

      #ifdef DLLCLASS_EXPORTS
      #define EXT_CLASS _declspec(dllexport)
      #else
      #define EXT_CLASS _declspec(dllimport) // 使用者
      #endif
      
      • 1
      • 2
      • 3
      • 4
      • 5

    导出的不是类,类是没有地址的,实际上导出的是类的成员函数地址

  • 相关阅读:
    kube-bench-CIS基准的自动化扫描工具学习
    Leetcode每日一题】 二维前缀和 - 矩阵区域和(难度⭐⭐)(31)
    redis主从从,redis-7.0.13
    【Java笔记+踩坑】设计模式——原型模式
    Logstash、sharding-proxy组件高级配置
    uboot内存相关命令操作
    微服务开发平台 Spring Cloud Blade 部署实践
    【电源专题】BUCK电源效率和输出电压的关系
    【pytest】 pytest拓展功能 pycharm PermissionError: [Errno 13] Permission denied:
    Sass/Scss 入门不慌
  • 原文地址:https://blog.csdn.net/first_bug/article/details/127845325