C++ Windows库程序

本文详细介绍了静态库和动态库的区别与联系,包括它们的特点、创建方法、使用方式及在C/C++语言中的具体应用。同时,还探讨了动态库的加载机制、函数导出与导入方式以及在类中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 静态库:运行时,不独立存在,会被嵌入(链接)到可执行程序或其他动态库中,目标程序的归档,文件扩展名: LIB
2 动态库:运行时独立存在,不会链接到可执行或其他动态库中,文件扩展名: DLL
3 静态库程序
     3.1 特点
       1)运行时不独立存在
       2)连接到可执行程序或其他动态库中
       3)目标程序的归档
     3.2 C语言的静态库  
        3.2.1 静态库的创建
 1)建立项目
 2)添加库程序,源文件.C文件
        3.2.2 静态库的路径设置
 1)项目的Setting菜单项中设置
 2)可以使用pragma关键字设置
    #pragma comment( lib, "../lib/WinClib.lib" )
    建立一个C文件,C文件可以在文件中直接使用C库函数,不需要头文件。
     3.3 c++语言的静态库
         3.3.1 静态库创建
   1)建立项目
   2)添加库程序,源文件.cpp文件
         3.3.2 静态库的使用
   1)项目的Setting菜单项中设置
   2)可以使用pragma关键字设置
   c++语言的静态库需要提供头文件,C语言最好也提供头文件。

   注意:CPP环境使用C静态库,库中函数的定义要增加 extern "C"
   例如:extern "C" int C_add(int, int);

4 动态库程序
     4.1 动态库程序的特点
        1)运行时独立存在
2)不会链接到可执行程序或其他动态库中
3)使用时加载
与静态库的比较
1)由于静态库是将源码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码的体积会增大。动态库的代码只需要一份,其他程序通过函数的地址使用,所以代码的体积小。
        2)静态库发生变化,使用(静态库的)程序需要重新编译连接嵌入到使用程序中。
    动态库发生变化,如果库中函数定义未发生改变,其他使用DLL的程序不需要重新编译连接。 
      4.2 动态库的创建
        4.2.1 建立项目
4.2.2 添加库程序
4.2.3 库程序导出
提供给使用者库中函数的信息,只有被导出的库程序才能被调用者使用。
     4.3 动态库的函数
        4.3.1 实现动态库函数
4.3.2 库函数的导出
 1)使用_declspec(dllexport) 导出函数,例如:_declspec(dllexport) int Sub(...);
    注意:编译连接之后,会有.LIB文件,是作为动态库函数映射使用,与静态库的LIB文件不同,动态库中对应的.lib文件表示函数在动态库中的偏移地址。
 2)定义模块文件 .def
 LIBRARY DLLFunc //库
EXPORTS     //库导出表
DLL_Mul @1 //导出的函数
    例如: 
      LIBRARY WinCdll(库名称)
      EXPORTS
        CDLL_add @1
        CDLL_sub @2
     4.4 动态库的使用
        4.4.1 隐式连接
  1)头文件和函数原型
    可以在函数原型的定义前增加_declspec(dllimport),例如:_declspec(dllimport) int Cdll_ADD(.....);
           2)导入动态库的LIB文件
     1)Setting菜单项中设置
     2)使用pragma关键字导入
           3)在程序中使用库函数
  4)隐式连接的情况,DLL可以存放的路径
     1.与可执行程序文件在同一目录下。
     2.当前工作目录
     3.WINDOWS目录
     4.WINDOWS/SYSTEM32目录
     5.WINDOWS/SYSTEM目录
     6.环境变量PATH指定目录,不建议使用

        4.4.2 显示连接, 不会用到.lib文件
  1)定义函数指针类型,typedef
  2)加载动态库
     HMODULE LoadLibrary(
LPCTSTR lpFileName   // 动态库的名称(.dll和.exe在一目录下)或全路径
 );//返回动态库的实例句柄。
  3)获取函数地址
     FARPROC GetProcAddress(
HMODULE hModule,    // 动态库实例句柄
LPCSTR lpProcName   // 函数名称
 );//执行成功,返回函数地址。
  4)使用函数
  5)卸载动态库
     BOOL FreeLibrary(
HMODULE hLibModule   // 动态库实例句柄
 );
      注意:
      显示连接,获取函数地址时,如果动态库的导出方式为_declspec(dllexport),那么获取函数地址失败。即 显示连接必须使用模块文件(.def)导出的函数,不能使用_declspec(dllexport)导出的函数。
      隐式连接,既可以通过在函数原型的定义前增加_declspec(dllimport),也可以使用模块文件(.def)导出函数。

        4.4.3 两种链接方式的对比
  1)在库函数定义不变的情况下
     隐式连接,由于库函数地址时在程序 编译连接,所以当动态库发生变化后,使用程序需要重新编译链接。
     显示连接,由于库函数地址是在程序 运行 过程中,动态从库中查询到的,所以库发生变化后不需要重新编译连接。
  2)动态库的加载时机不同
     隐式链接,动态库是在使用程序启动时就被加载,当动态库不存在,实用程序无法启动。
     显示链接,动态库是在调用LoadLibrary函数时才被加载,因此使用程序可以启动,只有程序执行到LoadLibrary函数时,才会出错。

5 DLL中类的使用
     5.1 DLL中定义并且实现一个类。
     5.2 DLL中类要导出
         在类名前增加_declspec(dllexport)
例如:
   class _declspec(dllexport) CMath
   {
    public:
      .............
   };
   通常使用预编译宏开关切换类的导入或导出,例如:
    #ifdef DLL_CLASS_EXPROTS
    #define EXT_CLASS _declspec(dllexport)
    #else
    #define EXT_CLASS _declspec(dllimport)
    #endif

   class EXT_CLASS CMath
   {
    public:
      .............
   };
     5.3 使用DLL中的类
        5.3.1 导入DLL的LIB文件
5.3.2 类的定义  CMath math;
5.3.3 使用类中的成员

6 动态库的程序入口
     入口函数不是DLL必须的,常用于DLL内部初始化或善后处理。
     动态库的加载和卸载时都会被调用,例如:调用LoadLibrary或 FreeLibrary函数时,会被调用
     BOOL WINAPI DllMain(
 HINSTANCE hinstDLL,  // 动态库程序实例句柄
 DWORD fdwReason,     // 调用原因
 LPVOID lpvReserved   // 保留
);返回TRUE,表示动态库加载成功。
fdwReason
DLL_PROCESS_ATTACH 进程被加载
DLL_PROCESS_DETACH 进程被卸载
DLL_THREAD_ATTACH  线程被加载
DLL_THREAD_DETACH  线程被卸载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值