• Windows动态库的使用 part one


    二.动态库程序
      这篇写得比较乱,看不懂的可以跳part 2,直接上图片的。
     
    动态库的使用:

    4.3.1 隐式链接

     动态库的隐式连接,需要动态库的 动态库文件".dll" , 动态库的LIB文件".lib" , 动态库的函数引入声明

      1)头文件和函数原型

      可以在函数原型的定义前,增加declspec(dllimport), 例如

      _declspec(dllimport)  int   FuncName( ... );

      如果库函数使用C格式导出,需要在函数定义增加 extern “C”

      2)导入动态库的LIB文件

     #pragma comment(lib,"libzmq-v100-mt-4_0_4.lib");    //第二个参数是LIB文件的名字,可带地址

      3)在程序中使用函数,像普通函数一样正常使用就好。

      4)隐式链接的情况,DLL可以存放的路径:

      (1)与执行文件中同一个目录下

      (2)当前工作目录

      (3)Windows目录

      (4)Windows/System32目录

      (5)Windows/System

      (6)环境变量PATH指定目录

          注意:高版本VC的配置文件

    4.3.2 显式链接

      1)定义函数指针类型

      2)加载动态库

      HMODULE LoadLibrary(

      LPCTSTR lpFileName  //动态库文件名或全路径

      ); 返回DLL的实例句柄(HINSTANCE)

      3)获取函数地址

      FARPROC GetProcAddress(

      HMODULE hModule,    //DLL句柄

      LPCSTR lpProcName   //函数名称

      ); 成功返回函数地址

      4)使用函数

      5)卸载动态库

      BOOL FreeLibrary(

      HMODULE hModule   //DLL的实例句柄

      );

    4.3.3 两种链接方式对比

    1)在库函数的定义不变情况下:

    隐式链接,由于库函数地址是在程序编译链接时设置,所以当动态库变化后,使用程序需要重新编译链接。

    显式链接,由于库函数地址是在程序执行时,动态的从库中查询,所以库变化后,不需要重新编译链接。 

    2)动态库加载

    隐式链接,动态库是在程序启动时就被加载,当DLL不存在,程序无法启动

    显式链接,动态库只在使用LoadLibrary函数,才会被加载。

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    下面是一些概述,我自己的笔记做得比较乱,只有自己才看得懂了。如果不想看的,可以直接看part 2的例子。

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    1.动态库特点

      1)运行时独立存在

      2)不会链接到执行程序

      3)使用时加载

    与静态库的比较:

      1)由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小。

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

    2.动态库的创建

      1 ) 建立项目

      2 ) 添加库程序

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

    3.动态库的使用

      3.1 隐式链接

      3.2 显式链接

    4.动态库的函数

      4.1 实现动态库的函数

      4.2 库函数的导出

      1) C++的导出

      使用 _declspec(dllexport) 导出函数

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

      2)C的导出方式     extern “C” _declspec(dllexport) int Sub(...);

      3)模块定义文件 .def

      例如:

      LIBRARY DLLFunc //库

      EXPORTS         //库导出表

      DLL_Mul  @1  //导出的函数


    4.3 库函数的使用

      4.3.1 隐式链接

      1)头文件和函数原型

      可以在函数原型的定义前,增加declspec(dllimport), 例如

      _declspec(dllimport)  int   FuncName( ... );

      如果库函数使用C格式导出,需要在函数定义增加 extern “C”

      2)导入动态库的LIB文件

     #pragma comment(lib,"libzmq-v100-mt-4_0_4.lib");    //第二个参数是LIB文件的名字,可带地址

      3)在程序中使用函数,像普通函数一样正常使用就好。

      4)隐式链接的情况,DLL可以存放的路径:

      (1)与执行文件中同一个目录下

      (2)当前工作目录

      (3)Windows目录

      (4)Windows/System32目录

      (5)Windows/System

      (6)环境变量PATH指定目录

          注意:高版本VC的配置文件

    4.3.2 显式链接

      1)定义函数指针类型

      2)加载动态库

      HMODULE LoadLibrary(

      LPCTSTR lpFileName  //动态库文件名或全路径

      ); 返回DLL的实例句柄(HINSTANCE)

      3)获取函数地址

      FARPROC GetProcAddress(

      HMODULE hModule,    //DLL句柄

      LPCSTR lpProcName   //函数名称

      ); 成功返回函数地址

      4)使用函数

      5)卸载动态库

      BOOL FreeLibrary(

      HMODULE hModule   //DLL的实例句柄

      );

    4.3.3 两种链接方式对比

    1)在库函数的定义不变情况下:

    隐式链接,由于库函数地址是在程序编译链接时设置,所以当动态库变化后,使用程序需要重新编译链接。

    显式链接,由于库函数地址是在程序执行时,动态的从库中查询,所以库变化后,不需要重新编译链接。 

    2)动态库加载

    隐式链接,动态库是在程序启动时就被加载,当DLL不存在,程序无法启动

    显式链接,动态库只在使用LoadLibrary函数,才会被加载。


    DLL中类的使用

    1.DLL中类的导出

    在类名称前增加 _declspec(dllexport) 定义,例如:

      class _declspec(dllexport) CMath {

      ...

      };

    通常使用预编译开关切换类的导入导出定义,例如:

      #ifdef DLLCLASS_EXPORTS

      #define EXT_CLASS _declspec(dllexport)//DLL

      #else

      #define EXT_CLASS _declspec(dllimport)//使用者

      #endif

      class EXT_CLASS CMath{

      ...

      };

    2.使用DLL中的类

      1 导入DLL的LIb

      2 类的定义

      3 使用类

    3.动态库的程序入口

      入口程序不是DLL必须的。常用于DLL内部初始化或善后处理。

      BOOL WINAPI DllMain(

        HINSTANCE hinstDLL, //动态库实例句柄

        DWORD fdwReason,    //被调用的原因

        LPVOID lpvReserved   //保留值

      ); 返回TRUE,表示动态库加载成功。

      动态库的加载或卸载时会被调用。例如:使用LoadLibrary或FreeLibrary时会被调用。

     附:

    制作动态库:
    1.新建选择倒数第2个:Win32 Dynamic-Link Library
    2.函数导出(生成lib文件以调用):_declspec(dllexport)
    3.Project/Settings/Links 设置 .dll 和 .ilk 的位置 复制.lib到指定存放位置

    4.使用库文件:
    C语言:
    extern "C"_declspec(dllimport)函数;
    #pragma comment(lib,"../lib/Cdll.lib")
    C++语言:
    _declspec(dllimport)函数;
    #pragma comment(lib,"../lib/CPPdll.lib")


    1.声明导出:
    将函数的偏移地址 导到了 和dll配套生成lib文件中
    2.模块文件
    将函数的偏移地址 导到了 dll文件 和 lib文件 各一份

    使用动态库
    1.隐式链接
    将dll文件内容导到内存的过程不需要程序员负责。
    链接器从lib文件中获取函数的偏移地址。
    2.显示链接
    将dll文件中内容导到内存的过程需要程序员自己负责。


    DLL中类的使用:
    1.DLL中类的导出 在类名称前增加 _declspec(dllexport) 定义,例如:
    class _declspec(dllexport) CMath { ... };
    2.通常使用预编译开关切换类的导入导出定义,例如:
    #ifdef DLLCLASS_EXPORTS
    #define EXT_CLASS _declspec(dllexport)//DLL
    #else
    #define EXT_CLASS _declspec(dllimport)//使用者
    #endif
    class EXT_CLASS CMath{ ... };
    ******* *******
    // 把这些写在头文件中,用户只要加上头文件就行了

     实现例子晚些再补上,可以参考这个:http://blog.sina.com.cn/s/blog_6fb3686501011ymn.html

  • 相关阅读:
    洛谷 U140360 购物清单
    洛谷 U140359 批量处理
    洛谷 U140358 操作系统
    洛谷U140357 Seaway连续
    洛谷 U141394 智
    洛谷 U141387 金
    CF1327F AND Segments
    刷题心得—连续位运算题目的小技巧
    CF743C Vladik and fractions
    洛谷 P6327 区间加区间sin和
  • 原文地址:https://www.cnblogs.com/sixbeauty/p/3639054.html
Copyright © 2020-2023  润新知