• C++ 静态、动态链接库的简单实现


    一、什么是静态链接库,什么是动态链接库?

    1、静态链接库就是你使用的.lib文件,库中的代码最后需要连接到你的可执行文件中去,所以静态连接的可执行文件一般比较大一些。在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.LIB),Visual C++的编译器在链接过程中将从静态库中恢复这些函数和数据并把它们和应用程序中的其它模块组合在一起生成可执行文件。这个过程称为“静态链接”。

    如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。

    可以参考:http://www.cnblogs.com/Winston/archive/2008/07/05/1236273.html

    1.1 windows下的静态链接库

          1、通用:

          格式如下:#prama comment(lib,"XXX.lib")

      2、针对开发环境:

    •   如果使用Visual C++:可以在Project Setting-->Link中加入你的静态库,也可以直接把该.lib文件加入到你的工程中。
    •   如果使用Visual Studio,位置在 项目→配置属性→连接器→输入→附加依赖项 中加入.lib文件。

    2、动态链接库英文为DLL,是Dynamic Link Library的缩写形式。所谓动态链接,就是把一些经常会共用的代码制作成DLL档,当可执行文件调用到DLL档内的函数时,windows操作系统才会把DLL档加载存储器内,DLL档本身的结构就是可执行文件,当程序需求函数才进行链接。通过动态链接方式,存储器浪费的情形将可大幅降低。

      动态链接库的加载方式分为两种:静态加载、动态加载。

    2.1 静态加载

      1、需求:

      • 服务端的头文件
      • 服务端所产生的lib文件和dll文件

      2、客户端加载:

      • #prama comment(lib,"XXX.lib")

    2.2 动态加载

        1、需求:

      • 服务端所产生的dll文件

      2、客户端加载:三步曲

      • LoadLibrary("DyLinkLib.dll")
      • GetProcAddress(hmod,"add");
      • FreeLibrary(hmod);

    二、代码示例

    1、静态链接库:

    • 服务端:工程名为StaticLibrary
    StaticLib.h:

    #ifndef ADD_H_
    #define ADD_H_

    int add(int a, int b);

    #endif

    
    
    StaticLib.cpp:
    
    int add(int a, int b)
    {
        return a+b;
    }

      产生:StaticLibrary.lib

    • 客户端:首先得将服务端的StaticLib.h头文件和StaticLibrary.lib文件发送给客户,这时客户端才能调用我们编写的静态链接库。
    #include "StaticLib.h"
    #include <iostream.h>
    
    #pragma comment(lib,"StaticLibrary.lib")
    //这里的lib好像过滤器功能,告诉编译器要使用lib文件,其次通过"StaticLibrary.lib"名字查找
    int main(void)
    {
        cout << add(3,4) << endl;
        return 0;
    }

    这里的静态链接库的链接采用windows平台静态链接的通用方式。


    小结:静态链接库的编写和普通函数的编写一样,没什么特大的区别

    2、动态链接库

    1. 静态加载方式
    • 服务端
    DystaticLink.h
    
    #ifdef MY_ADD
    #define ADD_H extern "C" _declspec(dllexport)
    #else
    #define ADD_H extern "C" _declspec(dllimport)
    #endif
    
    ADD_H int add(int a,int b);
    DystaticLink.cpp
    
    #define MY_ADD
    #include "DystaticLink.h"
    
    int add(int a,int b)
    {
        return a+b;
    }
    • 客户端
    #include <iostream.h>
    #include "DystaticLink.h"
    
    #pragma comment(lib,"DystaticLink.lib")
    
    int main()
    {
        cout << add(3,4);
        return 0;
    }

    小结:动态库的静态加载,需要服务端的"DystaticLink.h"头文件,以及服务端产生的DystaticLink.lib和DystaticLink.dll文件。

      2、动态加载

      动态加载可以参照:http://blog.sina.com.cn/s/blog_69e905cd0100m8zq.html

    • 服务端
    DyLinkLib.h:
    
    #ifdef ADD_H_
    #define ADD_H extern "C" _declspec(dllexport)
    #else
    #define ADD_H extern "C" _declspec(dllimport)
    #endif
    
    ADD_H int add(int a,int b);
    DyLinkLib.cpp
    
    #define ADD_H_ 
    #include "DyLinkLib.h"
    
    int add(int a,int b)
    {
        return a+b;
    }
    • 客户端
    #include <iostream.h>
    #include <windows.h>
    
    int main(void)
    {
        HMODULE hmod = LoadLibrary("DyLinkLib.dll");
        if (!hmod)
        {
            cout << "加载失败" << endl;
            return 0;
        }
        typedef int (*AddProc)(int a, int b);
        AddProc pAdd = (AddProc)GetProcAddress(hmod,"add");
        if (!pAdd)
        {
            cout << "获取地址失败!" << endl;
            return 0;
        }
        cout << pAdd(3,4) << endl;
        FreeLibrary(hmod);
        return 0;
    }
    • 解析:首先看一下大致流程
    • LoadLibrary
      The LoadLibrary function maps the specified executable module into the address space of the calling process. 
      
      For additional load options, use the LoadLibraryEx function. 
      
      HMODULE LoadLibrary(
        LPCTSTR lpFileName   // file name of module
      );

      1、LoadLibrary返回了模块句柄,这时,我们可以利用GetProcAddress函数得到动态库的某个函数地址。

      GetProcAddress
      The GetProcAddress function retrieves the address of an exported function or variable from the specified dynamic-link library (DLL). 
      
      FARPROC GetProcAddress(
        HMODULE hModule,    // handle to DLL module
        LPCSTR lpProcName   // function name
      );

      2、GetProcAddress函数返回一个函数指针,为了接收这个函数指针,我们的定义一个函数指针类型,这个函数指针类型要与要加载的动态库里的函数类型一致,此外还得将GetProcAddress返回值强制转换一下。

      typedef int (*AddProc)(int a, int b);
      AddProc pAdd = (AddProc)GetProcAddress(hmod,"add");

      3、得到了函数指针,我们就可以利用这个函数指针调用动态库的指定函数

      cout << pAdd(3,4) << endl;

      4、释放加载的动态库

      FreeLibrary(hmod);

    小结:动态加载时,只需服务端发送DyLinkLib.dll文件即可。

  • 相关阅读:
    GYM 101572C(模拟)
    GYM 101572A(单调队列优化dp)
    Codeforces 183C(有向图上的环长度)
    Codeforces 183A(坐标系性质)
    2019湘潭校赛 G(并查集)
    2019湘潭校赛 H(dp)
    2019湘潭校赛 E(答案区间维护)
    Codeforces 1141F2(贪心、预处理)
    Codeforces Round #411(Div. 2)——ABCDEF
    基数排序学习
  • 原文地址:https://www.cnblogs.com/aoguren/p/3161713.html
Copyright © 2020-2023  润新知