Windows的静态库与动态库

1.静态库

1.1 静态库特点

  • 运行不存在
  • 静态库源码被链接到调用程序中
  • 目标程序的归档

1.2 C语言静态库

  • C静态库的创建

    • 创建一个静态库项目。
    • 添加库程序,源文件使用C文件。
int Clib_add(int add1,int add2){
return add1+add2;
} int Clib_sub(int sub1,int sub2){
return sub1 - sub2;
}
  • C静态库的使用

    • 库路劲设置:可以使用pragma关键字设置
    • pragma comment(lib,"../lib/clib.lib")

#pragma comment(lib,"../Debug/Clib.lib")
#include <stdio.h>
#include <process.h>
int main(){
int sum,sub;
sum = Clib_add(5,3);
sub = Clib_sub(5,3); printf("sum=%d,sub=%d\n",sum,sub);
system("pause");
return 0;
}

1.3 C++语言静态库

  • C++静态库的创建

    • 创建一个静态库项目
    • 添加库程序,源文件使用cpp文件
int CPPlib_add(int add1,int add2){
return add1 + add2;
} int CPPlib_sub(int sub1,int sub2){
return sub1 - sub2;
}
  • C++静态库的使用

    • 库路径设置:可以使用pragma关键字设置
    • pragma comment(lib,"../lib/cpplib.lib")

#include <iostream>
using namespace std;
//给链接器看
int CPPlib_add(int add1,int add2);
int CPPlib_sub(int sub1,int sub2);
//给编译器看
#pragma comment(lib,"../Debug/CPPlib.lib") //?CPPlib_add@@YAHHH@Z / ?CPPlib_sub@@YAHHH@Z extern "C" int Clib_add(int add1,int add2);
extern "C" int Clib_sub(int sub1,int sub2);
#pragma comment(lib,"../Debug/Clib.lib") //Clib_add / Clib_sub
int main(){
//调c++库函数
int sum = CPPlib_add(5,4); //?CPPlib_add@@YAHHH@Z
int sub = CPPlib_sub(5,4); //?CPPlib_sub@@YAHHH@Z
cout << "sum=" << sum << ",sub=" << sub << endl; //调c库函数
sum = Clib_add(5,3); //?Clib_add@@YAHHH@Z 使用extern "C",编译时不换函数名-->Clib_add
sub = Clib_sub(5,3); //?Clib_sub@@YAHHH@Z -->Clib_sub
cout << "sum=" << sum << ",sub=" << sub << endl;
system("pause");
return 0;
}

2.动态库

2.1 动态库特点

  • 动态库的特点

    • 运行时独立存在
    • 源码不会链接到执行程序
    • 使用时加载(使用动态库必须使动态库执行)
  • 与静态库的比较

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

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

2.2动态库创建

  • 创建动态库项目

  • 添加库程序

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

    • 声明导出:使用_declspec(dllexport)导出函数

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

    制作动态库

    _declspec(dllexport) int CPPdll_add(int add1,int add2){
    return add1 + add2;
    } _declspec(dllexport) int CPPdll_sub(int sub1,int sub2){
    return sub1 - sub2;
    } _declspec(dllexport) int CPPdll_mul(int mul1,int mul2){
    return mul1 * mul2;
    }

    动态库原理图

    • 模块定义文件:.def

    例如:LIBRARY DLLFunc //库

    ​ EXPORTS //库导出表

    ​ DLL_Mul @1 //导出的函数

    不加声明导出

    int CPPdll_add(int add1,int add2){
    return add1 + add2;
    } int CPPdll_sub(int sub1,int sub2){
    return sub1 - sub2;
    } int CPPdll_mul(int mul1,int mul2){
    return mul1 * mul2;
    }

    添加模块定义导出文件

    LIBRARY	CPPDll
    EXPORTS
    CPPdll_add @1
    CPPdll_sub @2
    CPPdll_mul @3

2.3动态库的使用

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

    1. 头文件和函数原型

      ​ 可以在函数原型的声明前,增加_declspec(dllimport)

    2. 导入动态库的LIB文件

    3. 在程序中使用函数

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

      • 与执行文件中同一个目录下(建议放在此目录下)
      • 当前工作目录
      • Windows目录
      • Windows/System32目录
      • Windows/System
      • 环境变量PATH指定目录
    #include <iostream>
    using namespace std; _declspec(dllimport)int CPPdll_add(int add1,int add2);
    _declspec(dllimport)int CPPdll_sub(int sub1,int sub2);
    _declspec(dllimport)int CPPdll_mul(int mul1,int mul2);
    //通知链接器到哪抓编号和dll文件名(CPPDll.dll)
    #pragma comment(lib,"../Debug/CPPDll.lib") int main(){
    int sum = CPPdll_add(5,4);
    int sub = CPPdll_sub(5,4);
    int mul = CPPdll_mul(5,4);
    cout << "sum=" << sum << ",sub=" << sub << ",mul=" << mul << endl;
    system("pause");
    return 0;
    }
  • 显示链接(程序员自己负责使动态库执行)

    1. 定义函数指针类型 typedef

    2. 加载动态库

      HMODULE LoadLibrary(
      LPCTSTR lpFileName //动态库文件名或全路劲
      ); //返回DLL的实例句柄(HINSTANCE)
    3. 获取函数地址

      FARPROC GetProcAddress(
      HMODULE hModule //DLL句柄
      LPCSTR lpProcName //函数名称
      ); //成功返回函数地址
    4. 使用函数

    5. 卸载动态库

      BOOL FreeLibrary(
      HMODULE hModule //DLL的实例句柄
      );
    #include <iostream>
    #include <Windows.h>
    using namespace std; typedef int(*FUNC)(int m,int n);
    int main(){
    HINSTANCE hDll = LoadLibrary("CPPDll.dll");
    cout << "hDll:" << hDll << endl; FUNC add = (FUNC)GetProcAddress(hDll,"CPPdll_add");
    cout << "addAdress:" << add << endl;
    int sum = add(5,4);
    cout << "sum:" << sum << endl; FUNC sub = (FUNC)GetProcAddress(hDll,"CPPdll_sub");
    cout << "subAdress:" << sub << endl;
    int su = sub(5,4);
    cout << "sub:" << su << endl; FUNC mul = (FUNC)GetProcAddress(hDll,"CPPdll_mul");
    cout << "mulAdress:" << mul << endl;
    int mu = mul(5,4);
    cout << "mul:" << mu << endl; system("pause");
    FreeLibrary(hDll);
    return 0;
    }

2.4动态库中封装类

  • 在类名称前增加_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{
    ...
    };

    例子:

    头文件

    #ifndef _ClASSDLL_H
    #define _CLASSDLL_H #ifdef DLLCLASS_EXPORTS
    #define EXT_CLASS _declspec(dllexport) //dll
    #else
    #define EXT_CLASS _declspec(dllimport) //使用者
    #endif class EXT_CLASS CMath{
    public:
    int add(int m,int n);
    int sub(int m, int n);
    }; #endif

    源文件

    #define DLLCLASS_EXPORTS
    #include "ClassDll.h" int CMath::add(int m,int n){
    return m + n;
    } int CMath::sub(int m,int n){
    return m - n;
    }

    调用动态库中的封装类

    #include "..\ClassDll\ClassDll.h"
    #include <iostream>
    using namespace std;
    #pragma comment(lib,"../Debug/ClassDll.lib") int main(){
    CMath myMath;
    int sum = myMath.add(5,4);
    int sub = myMath.sub(5,4);
    cout << "sum=" << sum << ",sub=" << sub << endl;
    system("pause");
    return 0;
    }

Windows的静态库与动态库的更多相关文章

  1. Windows下静态库与动态库的创建与使用

    Windows下静态库与动态库的创建与使用 学习内容:本博客介绍了Windows下使用Visual C++ 6.0制作与使用静态库与动态库的方法. --------CONTENTS-------- 一 ...

  2. Windows静态库和动态库的创建和使用

    偶们在实际的编程开发中,经常会遇到运行时无法找到某个DLL文件或者链接时无法找到某个LIB文件.然后,我们就开始乱GOOGLE一下,然后将VS2005的设置改变一下,或许就Ok了,我们将别人开发的DL ...

  3. Windows下静态库、动态库的创建和调用过程

    静态库和动态库的使用包括两个方面,1是使用已有的库(调用过程),2是编写一个库供别人使用(创建过程).这里不讲述过多的原理,只说明如何编写,以及不正确编写时会遇见的问题. //注:本文先从简单到复杂, ...

  4. C语言静态库与动态库(Windows下测试)

    转载于:https://zhidao.baidu.com/question/1946953913764139388.html,原文为Linux上测试,本文为在Windows上编译测试 我们通常把一些公 ...

  5. Windows静态库和动态库的创建和使用(VS2005)

    偶们在实际的编程开发中,经常会遇到运行时无法找到某个DLL文件或者链接时无法找到某个LIB文件.然后,我们就开始乱GOOGLE一下,然后将VS2005的设置改变一下,或许就Ok了,我们将别人开发的DL ...

  6. C++ 静态库与动态库以及在 Windows上 的创建、使用

    一.什么是库 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可以 ...

  7. 【C/C++开发】C++静态库与动态库以及在Linux和Windows上的创建使用

    原文出处: 吴秦的博客    这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学 ...

  8. C++ 系列:静态库与动态库

    转载自http://www.cnblogs.com/skynet/p/3372855.html 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择 ...

  9. C++静态库与动态库

    C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一 ...

随机推荐

  1. 23.Quick QML-简单且好看的图片浏览器-支持多个图片浏览、缩放、旋转、滑轮切换图片

    之前我们已经学习了Image.Layout布局.MouseArea.Button.GroupBox.FileDialog等控件. 所以本章综合之前的每章的知识点,来做一个图片浏览器,使用的Qt版本为Q ...

  2. LINQ之方法语法

    上节讲到使用linq的查询关键字进行查询,这节讲一下linq查询的另一种方式--linq方法. 使用linq方法语法,必须要会用lambda表达式,配合lambda表达式才能体会到linq的优雅便捷. ...

  3. redis 未授权访问(写公钥、写计划任务)

    写公钥 ssh-keygen -t rsa # 生成key (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") & ...

  4. 《Spring 手撸专栏》第 2 章:小试牛刀(让新手能懂),实现一个简单的Bean容器

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 上学时,老师总说:不会你就问,但多数时候都不知道要问什么! 你总会在小傅哥的文章前言 ...

  5. 定义私有属性: *String name; * int age; * String gender; * int salary; Date hiredate;//入职时间

    import java.text.SimpleDateFormat; import java.util.Date; /** * 定义私有属性: * String name; * int age; * ...

  6. TrueCrypt与CryptSetup双系统全盘加密(图文)

    http://blog.topsec.com.cn/truecrypt%E4%B8%8Ecryptsetup%E5%8F%8C%E7%B3%BB%E7%BB%9F%E5%85%A8%E7%9B%98% ...

  7. rsync+inotify实现全网自动化数据备份

    第1章 环境配置 实例1-1 服务器及IP主机名规划 已知 4 台服务器主机名主机对应信息见下表: 服务器说明 外网 IP(NAT) 内网 IP(NAT)  主机名 web服务器 10.0.0.7/2 ...

  8. k8s集群部署(2)

    一.利用ansible部署kubernetes准备阶段 1.集群介绍 基于二进制方式部署k8s集群和利用ansible-playbook实现自动化:二进制方式部署有助于理解系统各组件的交互原理和熟悉组 ...

  9. ELK学习实验020:ELK使用kafka缓存

    首先安装一个kafka集群,但是zookeeper使用单节点,可以让kafka快速跑起来,后续再研究kafka和zokkeeper的集群 1 安装Kafka集群 下面是三个节点都要做 [root@no ...

  10. Linux 文件隐藏属性-创建文件默认权限

    Linux特殊权限介绍 # password原本只有root可以访问但是为什么普通用户在修改密码的时候也可以改里面的内容. [root@gong ~]# ll /usr/bin/passwd -rws ...