zoukankan      html  css  js  c++  java
  • C++ 动态库和静态库

    目的:代码重用

    静态库

     创建头文件testlib.h

    #ifndef TESTLIB_H
    #define TESTLIB_H
    // 防止头文件重复包含
    // 条件编译指令
    // 加减乘除
    int add(int a, int b);
    
    #endif 

    创建testlib.cpp

    #include "pch.h"
    #include "framework.h"
    #include "testlib.h"
    
    
    int add(int a, int b) {
        return a + b;
    }

    生成解决方案

    1>------ 已启动生成: 项目: testlib, 配置: Debug Win32 ------
    1>pch.cpp
    1>testlib.cpp
    1>testlib.vcxproj -> C:UsersMysource
    epos	estlibDebug	estlib.lib
    ========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

    创建新的控制台项目testdll

    右键项目,属性,链接器,附加库目录 C:UsersMysource epos estlibDebug或相对路径(推荐)

    使用lib

    #include <iostream>
    #include "../../testlib/testlib/testlib.h"
    #pragma comment(lib, "testlib.lib")
    
    int main()
    {
        printf("请输入两个数字
    ");
        int a, b;
        scanf("%d%d", &a, &b);
        printf("add(a, b)=%d
    ", add(a, b));
        return 0;
    }

    只需提供头文件和lib文件就可以使用你提供的静态库

    动态库

     静态库生成的文件全都组合到exe里面

    动态库则动态加载,不会嵌入到exe中

    vs总文件有好几个G大,但是其exe文件只有几个KB,dll的好处

    软件升级,只需要更新动态库重启软件就好了,不需要重新安装新的的编译文件

    1.VS2019新建立一个空项目(Project1)

    VS有提供dll项目的模板,可是对于我来说反而搞不懂模板中的文档,于是建立空白项目,自己去做简单的配置。

    2.解决方案管理器中为项目添加一个头文件,选择新建项

    在新建的头文件(testdll.h)中声明要导出的API,添加函数声明

    #ifndef TESTDLL_H
    #define TESTDLL_H
    int add(int a, int b);
    int sub(int a, int b);
    #endif // !TESTDLL_H

    3.添加一个源文件,实现申明的API函数

    #include "testdll.h"
    
    int add(int a, int b) {
        return a + b;
    }
    
    int sub(int a, int b) {
        return a - b;
    }

    4.修改项目->项目属性->常规->配置类型为动态库(.DLL)

    生成解决方案

    1>------ 已启动生成: 项目: testdll, 配置: Debug x64 ------
    1>testdll.cpp
    1>testdll.vcxproj -> C:UsersMysource
    eposProject1DebugProdect1.dll
    ========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

    将dll文件拖到dependency walker中

     需要添加,声明导出函数

    #pragma once
    #ifndef TESTDLL_H
    #define TESTDLL_H
    __declspec(dllexport) int add(int a, int b);
    __declspec(dllexport) int sub(int a, int b);
    #endif // !TESTDLL_H

    重新生成

     使用动态库有两种方式

    隐式调用动态库

    在project1项目中添加预定义

    修改  testdll.h

    #ifndef TESTDLL_H
    #define TESTDLL_H
    
    #ifdef _DLLAPI
      #define DLLAPI __declspec(dllexport) 
    #else 
      #define DLLAPI __declspec(dllimport)
    #endif // !DLLAPI
    
    int DLLAPI add(int a, int b);
    int DLLAPI sub(int a, int b);
    
    #endif // !TESTDLL_H

    如果DLLAPI定义了,则DLLAPI是__declspec(dllexport) ,因为刚刚预定义了所以是__declspec(dllexport) 。但在testd项目中我们没有预定义因此是__declspec(dllimport) 。

    添加项目testdll

     右键项目,属性,C/C++,常规,附加包含目录

     否则无法导入头文件

    #include <iostream>
    #include "./testdll.h"
    #pragma comment(lib, "Project1.lib")
    
    int main()
    {
        printf("请输入两个数字
    ");
        int a, b;
        scanf("%d%d", &a, &b);
        printf("add(a, b)=%d
    ", add(a, b));
        return 0;
    }

    右键项目,属性,链接器,附加库目录,C:UsersMysource eposProject1Debug

     SDL检查 否

     运行

    显示调用动态库

    修改testdll.cpp

    #include <iostream>
    #include "./testdll.h"
    //#pragma comment(lib, "Project1.lib")
    #include <Windows.h>
    
    // 定义函数指针类型
    typedef int (*PADD)(int a, int b);
    
    int main()
    {
        printf("请输入两个数字
    ");
        int a, b;
        scanf("%d%d", &a, &b);
        // 加载dll文件
        HMODULE hDLL = LoadLibrary(L"C:\Users\My\source\repos\Project1\Debug\Project1.dll");
        if (hDLL == NULL)
        {
            printf("加载失败
    ");
            return 0;
        }
        
        PADD padd = (PADD)GetProcAddress(hDLL, "add");
    
        printf("add(a, b)=%d
    ", padd(a, b));
    
    FreeLibrary(hDLL);
    return 0; }

    运行程序,会报异常,找不到add函数

    查看dependency walker

     复制函数名,修改上面程序

     PADD padd = (PADD)GetProcAddress(hDLL, "?add@@YAHHH@Z");

    运行正常

     C语言可以直接使用add,但C++不行

    因此,我们要导入C语言的配置

    修改testdll.h

    #ifdef _DLLAPI
    #define DLLAPI __declspec(dllexport) 
    #else 
    #define DLLAPI __declspec(dllimport)
    #endif // !DLLAPI
    extern "C" DLLAPI int add(int a, int b);
    extern "C" DLLAPI int sub(int a, int b);
    #endif // !TESTDLL_H

    重新生成Project1

    函数改为add,可正常运行testdll

    为了这个改名,微软还提供了模块定义文件

    头文件testdll.h

    #pragma once
    #ifndef TESTDLL_H
    #define TESTDLL_H
    
    int add(int a, int b);
    int sub(int a, int b);
    
    #endif // !TESTDLL_H

    添加新建项,代码,模块定义文

    LIBRARY Project1
    EXPORTS
    add
    sub

    重新生成

    运行testdll

  • 相关阅读:
    nyoj 117 求逆序数 (归并(merge)排序)
    2018年四川理工学院软件工程考试大纲(软件需求分析)
    2018年四川理工学院软件工程考试大纲(软件计划与可行性研究)
    hdu 1166 敌兵布阵 (线段树、单点更新)
    hdu 1754 I Hate It (线段树、单点更新)(PS:ios::sync_with_stdio(false)可以加快cin、cout的读取写出速度)
    周末手撸管理系统(一)
    drf源码save以及response
    drf框架serializers中ModelSerializer类简化序列化和反序列化操作
    drf框架序列化和返序列化
    django模型中有外键关系的表删除相关设置
  • 原文地址:https://www.cnblogs.com/aidata/p/13159001.html
Copyright © 2011-2022 走看看