总结一下动态链接库和静态链接库。1

首先搞清楚几个概念:

静态库:函数和数据被编译进一个二进制文件,通常扩展名为.lib。在使用静态库的情况下,在编译连接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.exe文件)。

动态库:在使用动态库的时候,往往提供两个文件:1.引入库(.lib)和.dll。引入库包含被Dll导出的函数和变量的符号名,Dll包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,Dll中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载Dll,访问Dll中导出的函数。

静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(Dll)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从Dll中寻找相应函数代码,因此需要相应Dll文件的支持。

Lib:静态链接库和动态链接库都会生成.lib文件,但.lib文件却有着不同的内容。

目标库(Object Libraries)

目标库又叫静态链接库,是扩展名为.LIB的文件,包括了用户程序要用到 的各种函数。它在用户程序进行链接时,“静态链接”到可执行程序文件当中。例如,在VC++中最常使用到的C运行时目标库文件就是LIBC.LIB。在链 接应用程序时常使用所谓“静态链接”的方法,即将各个目标文件(.obj)、运行时函数库(.lib)以及已编译的资源文件(.res)链接到一起,形成 一个可执行文件(.exe)。使用静态链接时,可执行文件需要使用的各种函数和资源都已包含到文件中。这样做的缺点是对于多个程序都使用的相同函数和资源 要重复链接到exe文件中,使程序变大、占用内存增加。

导入库(Import Libraries)

导入库是一种特殊形式的目标库文件形式。和目标库文件一样,导入库文件的扩展名也是.LIB,也是在用户程序被链接时,被“静态链接”到可执行文件当中。但是不同的是,导入库文件中并不包含有程序代码。相应的,它包含了相关的链接信息,帮助应用程序在可执行文件中建立起正确的对应于动态链接库的重定向表。比如KERNEL32.LIB、USER32.LIB和GDI32.LIB就是我们常用到的导入库,通过它们,我们就可以调用Windows提供的函数了。 如果我们在程序中使用到了Rectangle这个函数,GDI32.LIB就可以告诉链接器,这个函数在GDI32.DLL动态链接库文件中。这样,当用 户程序运行时,它就知道“动态链接”到GDI32.DLL模块中以使用这个函数。其实说白了导入库就是一个索引,一个dll动态链接库的索引表,这是我的 理解。

Dll:

“动态链接”是将一些公用的函数或资源组织成动态链接库文件(.dll),当某个需要使用dll中的函数或资源的程序启动时(准确的说是初始化时),系统将该 dll映射到调用进程的虚拟地址空间、增加该dll的引用计数值,然后当实际使用到该dll时操作系统就将该dll载入内存;如果使用该dll的所有程序 都已结束,则系统将该库从内存中移除。使用同一dll的各个进程在运行时共享dll的代码,但是对于dll中的数据则各有一份拷贝(当然也有在dll中共享数据的方法)。 动态链接库中可以定义两种函数:输出函数和内部函数。输出函数可以被其他模块调用,内部函数只能被动态链接库本身调用。动态链接库也可以输出数据,但这些数据通常只被它自己的函数所使用。

.h文件:头文件,变量及函数声明就在.h文件中。

.pdb文件:用来帮助软件进行调试的,无论是静态链接库、动态链接库的静态调用、动态调用只要有.pdb文件就能进行调试。

extern "C":不发生名字改编,解决C++和C语言之间调用时名字改编的问题,加上之后不改变函数名。extern "C"只能用来导出全局函数,不能导出类和类的成员函数。我想大概是因为C中没有类和类的成员变量吧。

__declspec(dllexport):表示该函数为DLL输出函数,即其他应用程序可以调用该函数

一、静态链接库

静态链接库只生成.lib文件,使用的时候直接用头文件和.lib文件即可。

头文件:

#pragma once
int Add(int a, int b);int Sub(int a, int b);class Student
{
public:virtual char *GetName() const;virtual void SetName(char *Name);virtual int  GetAge() const;virtual void SetAge(int age);virtual void Output();private:char *m_strName;int   m_nAge;};

源程序:

#include "stdafx.h"
#include "Sample.h"
#include <iostream>using namespace std;int Add(int a, int b)
{return a + b;
}int Sub(int a, int b)
{return a - b;
}char * Student::GetName() const
{return m_strName;
}void Student::SetName(char * Name)
{m_strName = Name;
}int Student::GetAge() const
{return m_nAge;
}void Student::SetAge(int age)
{m_nAge = age;
}void Student::Output()
{std::cout << "Name: " << m_strName << std::endl << "Age: " << m_nAge << std::endl;
}

测试程序:

#include "stdafx.h"
#include <iostream>
#include "Sample.h"using namespace std;int main()
{int sum = 0;int a = 5;int b = 3;sum = Add(a, b);cout << "sum = a + b = " << sum << endl;int diff = 0;diff = Sub(a, b);cout << "diff = a - b = " << diff << endl;Student xiaoming;xiaoming.SetAge(27);xiaoming.SetName("xiaoming");xiaoming.Output();int age = xiaoming.GetAge();char *name = xiaoming.GetName();cout << "Name:" << name << endl << "Age:" << age << endl;system("pause");return 0;
}

二、动态链接库

生成动态连接库的程序是一致的,但不同是调用方式,动态链接库有动态调用和静态调用两种方式。

在导出函数的时候,两者可以一样,都使用

#ifdef DLL_IMPLEMENT
#define DLL_API extern "C" __declspec(dllexport)
#else
#define DLL_API extern "C" __declspec(dllimport)
#endif

这个宏。其中个的extern “C”是为了解决C++名字改编的问题,在动态调用时比较有用,因为动态调用需要根据函数名来获取函数地址,如果不加这个,动态调用的函数名将会发生改编,将找不到函数;静态连接就不需要这个。

导出类就不同了,导出类在静态调用动态链接库的情况下,可以直接用__declspec(dllexport)导出类,此时这个类就能正常使用了。在动态调用的情况下,这样直接导出的类是没有地址的,用不了,且它的名字也会发生改变(个人看法)。我一般的用法是使用一个Create函数,Create里面是return new CClass,即这个类的实例化,函数类型是CClass *,整个函数可以理解为CClass class = new CClass。当然动态调用的时候加上了extern “C”,这样可以通过函数名找到函数地址。此时类的成员变量仍然不能用,因为成员函数都没有地址,找不到,因为我不能通过这个类来找到它成员函数的地址,这里把成员函数声明为虚函数,这样就可以了。因为虚函数在类中有一个虚函数表,通过这个虚函数表可以找到类中所有虚函数的地址,这就是我动态调用Dll导出类的方法。

1. 动态链接库的静态调用

头文件文件:需要在预编译器里面定义宏DLL_IMPLEMENT

#pragma once#ifdef DLL_IMPLEMENT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif // DLL_APIDLL_API int Add(int a, int b);DLL_API int Sub(int a, int b);class DLL_API Student
{
public:char *GetName() const;void SetName(char *Name);int  GetAge() const;void SetAge(int age);void Output();private:char *m_strName;int   m_nAge;};

源文件:

#include "stdafx.h"
#include <iostream>
#include "Sample.h"int Add(int a, int b)
{return a+b;
}int Sub(int a, int b)
{return a - b;
}char * Student::GetName() const
{return m_strName;
}void Student::SetName(char * Name)
{m_strName = Name;
}int Student::GetAge() const
{return m_nAge;
}void Student::SetAge(int age)
{m_nAge = age;
}void Student::Output()
{std::cout << "Name: " << m_strName << std::endl << "Age: " << m_nAge << std::endl;
}

测试文件:

// testStaticDll.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <iostream>
#include "sample.h"using namespace std;int main()
{int sum = 0;int diff = 0;int a = 5;int b = 3;sum = Add(a, b);diff = Sub(a, b);cout << "sum = a + b = " << sum << endl;cout << "diff = a - b = " << diff << endl;分隔符Student xiaoming;xiaoming.SetAge(27);xiaoming.SetName("xiaoming");xiaoming.Output();char *sName = xiaoming.GetName();int  nAge = xiaoming.GetAge();cout << "Name: " << sName << endl << "Age: " << nAge << endl;system("pause");return 0;
}

2. 动态链接库的动态调用

头文件

#pragma once#ifdef DLL_IMPLEMENT
#define DLL_API extern "C" __declspec(dllexport)
#else
#define DLL_API extern "C" __declspec(dllimport)
#endif DLL_API int Add(int a, int b);DLL_API int Sub(int a, int b);class Student
{
public:virtual char *GetName() const;virtual void SetName(char *Name);virtual int  GetAge() const;virtual void SetAge(int age);virtual void Output();private:char *m_strName;int   m_nAge;};DLL_API Student *Create();

源文件:

#include "stdafx.h"
#include <iostream>
#include "Sample.h"int Add(int a, int b)
{return a+b;
}int Sub(int a, int b)
{return a - b;
}Student * Create()
{return new Student;
}char * Student::GetName() const
{return m_strName;
}void Student::SetName(char * Name)
{m_strName = Name;
}int Student::GetAge() const
{return m_nAge;
}void Student::SetAge(int age)
{m_nAge = age;
}void Student::Output()
{std::cout << "Name: " << m_strName << std::endl << "Age: " << m_nAge << std::endl;
}

测试文件:

// testDynamicDll.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include "windows.h"
#include "sample.h"
#include <iostream>using namespace std;
typedef int(*Fun)(int , int );
typedef Student *(*CreateFunc)();
int main()
{HINSTANCE hIns = NULL;hIns = LoadLibrary(_T("DllFunc.dll"));if (hIns == NULL){cout << "Dll加载失败" << endl;system("pause");return 0;}Fun Sum = (Fun)GetProcAddress(hIns, "Add");int sum = 0;int a = 5;int b = 3;sum = Sum(a, b);cout << "sum = a + b = " << sum << endl;Fun Diff = (Fun)GetProcAddress(hIns, "Sub");int diff = 0;diff = Diff(a, b);cout << "diff = a - b = " << diff << endl;CreateFunc CreateStudent = (CreateFunc)GetProcAddress(hIns, "Create");Student *xiaoming = CreateStudent();xiaoming->SetAge(27);xiaoming->SetName("xiaoming");xiaoming->Output();int age = xiaoming->GetAge();char *name = xiaoming->GetName();cout << "Name:" << name << endl << "Age:" << age << endl;FreeLibrary(hIns);system("pause");return 0;
}

静态链接库、动态链接库使用方法相关推荐

  1. mingw编译opencv动态链接库和静态链接库及使用方法

    前言 我一直不知道编译的过程以及cmake, make 这些工具是干什么的,所有抽时间研究了一下. 简单来说就是 cmake 是根据 CMakeLists.txt 用来生成 makefile文件的.而 ...

  2. VC的静态链接库 动态链接库

    1.什么是静态连接库,什么是动态链接库         静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了. ...

  3. VS动态/静态链接库的使用方法

    c++的链接库库分为静态.动态链接库两种.使用静态库编译时为静态编译,静态编译将静态库中的代码编译进程序,生成的程序能够独立运行.而使用动态链接库在编译时为动态编译,动态编译不将动态库中的代码编译进程 ...

  4. 静态链接库(Lib) 与 动态链接库(DLL)

    静态链接库(Lib) 与 动态链接库(DLL) 一.VS中添加LIb库及头文件(外部依赖项)的步骤: 1.添加工程的头文件目录:工程-属性-配置属性-c/c+±–常规-附加包含目录:加上头文件存放目录 ...

  5. 静态链接库,动态链接库【滴水逆向三期48笔记】

    在开发过程中,我们通常会有很多函数,需要多次使用或在不同的程序中使用该函数,也有可能我们会将我们写好的函数给别人使用,但是我们又不想给他源代码,毕竟代码是我们花了很多功夫写出来的,那么我们如何不发给其 ...

  6. C++ 动态链接库和静态链接库

      今天对C++生成动态链接路和静态链接库非常感兴趣,必须搞定,否则都没有心情干其他事了.Let's go~ 文章目录 源程序编译链接生成文件格式 预编译 编译和优化 编译 优化 生成目标文件 链接 ...

  7. 动态连接库和静态链接库

    文章出处:http://www.cnblogs.com/gaoyihan/p/4723332.html 本文参考了以下博客:      1. http://blog.csdn.net/gamecrea ...

  8. C++动态链接库dll及静态链接库lib制作及使用教程

    现需将C++函数封装成动态链接库dll,网上看了好多博客教程,说的都不够全面,现提供一个很有用的视频,亲测有效,启发很大,附上链接: 视频网址 下面自己根据视频记录下制作动态链接库dll过程,防止忘记 ...

  9. 静态链接库与动态链接库 (二)动态链接库的编译与使用

    上一篇文章里大概描述linux下静态链接库的编译与使用,下面讲动态链接库的编译与使用方法. 1. 什么是动态链接库 所谓动态链接库,是指编译的时候不会把程序引用到的库插入到执行程序里,而是在执行时候才 ...

最新文章

  1. mouseOver/mouseOut 与 rollOver/rollOut的区别
  2. Pixhawk-串级pid介绍
  3. python源文件改写编写一个程序读取一个python源程序文件_学PYTHON第三节:编译和解释...
  4. spark dataframe学习记录
  5. c# 溢出抛异常_C#中的int是否没有溢出异常?
  6. vi/vim编辑器使用方法详解
  7. 使用STL标准模板库实现的个人通讯录
  8. 机电一体化柔性生产线加工系统
  9. Soul App 后台Api接口
  10. java 502错误_Spring Boot连接超时导致502错误的实战案例
  11. android ViewPager2的使用教程
  12. 解读翻译李飞飞-Hiding Data With Deep Networks
  13. linux 薄膜键盘驱动,一份*级薄膜键盘的简历— HHKB 静电容 键盘
  14. deepin efi 启动u盘_deepin启动引导修复教程
  15. 如何用PDF编辑器编辑、修改PDF文本和图片?
  16. 【英译中】如何拍好沙滩照1——2014年7月23日
  17. 台湾南投3.27地震
  18. 开发应用程序的Andr​​oid - 入门
  19. Flutter入门实战教程:从0到1仿写web版掘金App (完结)
  20. 【2022国赛模拟】无损加密——LGV引理、状压DP

热门文章

  1. AOS加性算子分裂法
  2. 手机上如何压缩PDF文件大小
  3. bulter机器人_浅谈国内外9大智能物流机器人
  4. 仓储搬运机器人_浅谈仓储搬运机器人那点事儿
  5. 三菱fx3u+485ADP-MB与3台台达变频器modbus通讯程序 通过三菱fx3u 485ADP-MB板对3台台达变频器进行modbus通讯,实现频率设定,启停控制,输出频率读取,输出电压读取
  6. js图片大小压缩到指定范围
  7. 俞敏洪:我让女儿主动学习的秘密,做家长的都该看看!
  8. 吉他入门-免费吉他教学大全 技术服务
  9. 手机广角相机标定和畸变校正
  10. 超声后端图像处理-概述