c++ windows 蓝牙库_跟我学c++中级篇——Windows下的动态库

本文详细介绍了Windows平台下动态库的区别和复杂性,包括.dll与.lib文件的作用,动态库的创建与应用,以及导出函数和类的方法。同时,讨论了动态库的管理要点,如版本控制和避免DLL Hell。最后,提到了常用的库分析工具,如dumpbin、Depends和逆向工程工具IDAPRO、Ollydbg、Windbg。

1520499acf636f7587101a993c4a83c1.png

一、Windows下的动态库

前面学习了Linux下的库的开发应用过程,现在回过头看看Windows。如果用比较容易明白的话来区别二者的不同的话,应该是“Windows平台的库混杂了微软自己很多的东西,看似简单,但比Linux下的库要复杂很多”。写过跨平台开发的程序都知道,在Windows平台下,动态库也要带着.lib文件,否则在编译链接时就会报错。
其实微软的想法非常简单,正如平时处理工具,把工具分得清楚明白不更好寻找和使用么。想法是很好的,可工具量少啊,如果工具海量并且经常更新换代,细节的管控,反而成为了累赘。这是什么意思呢?就是说在库本身的文件中,包含了大量的和细节相关的数据,比如符号的地址,库的类型等。
实际上在Windows平台上进行库编译时,需要根据不同的二进制文件来进行区分。.dll文件是真正的库文件,也就是和LINUX下的SO一样,是动态链接时的共享对象。那么为什么还要有一个.lib文件呢?原因就在于,微软为了方便链接,一些细节的符号表就在这个文件中,而在LINUX的动态库使用过程中,已经说明了,查找共享资源映射内存,这些符号表是必不可少的,到这里就明白了吧。这也是为什么很多新手上来后,发现动态库和静态都有一个lib文件,但是前者的文件要小很多。微软的意思比较明确,有了这些符号表,就可以在编译期控制一些东西而不是像LINUX,有些符号最终会使用装载器来映射查找。
此外,微软还搞了一些导出符号的规定,而这些规定在X64平台又基本都失效了。比如__stdcall啥的,在X64平台上只有一个fastcall了。其它的小零碎如def文件啥的,看上去应用很方便,其实挺复杂的。这也是著名的DLL HELL的发轫。
正如一个人有一个好的初衷,事情却干得不咋滴一样,可以理解。

二、动态库的应用

搞一个小的动态库,32位的,目的是讲解DLL的导入导出方法,包括函数、类,具体到一些细节,如导出静态变量等,请同学们自行查找相关资料:

//DllPro.h
#pragma once
//extern "C":做为纯C接口方式导出,这个适合跨语言,c++中使用可省略
//__stdcall :默认即是
//下面的宏定义的意思:定义MYDLL_API为后面的导入约定,
//通过宏MYDLL_EXPORTS,来确定具体使用哪种情形
//看下面的使用方式就明白了
#ifdef MYDLL_EXPORTS
#define  MYDLL_API extern "C" __declspec(dllimport)
#else
#define  MYDLL_API  extern "C" __declspec(dllexport)
#endif

MYDLL_API int Sum(int a, int b);
MYDLL_API int Mul(int c, int d);

//DllPro.cpp
#include "stdafx.h"
#include "DllPro.h"

MYDLL_API int Sum(int a, int b){
    return a + b;
}
MYDLL_API int Mul(int c, int d){
    int ret = 0;
    for (int num = 0; num     {
        ret += c;
    }

    return ret;
}

//ExportData.h
#pragma once
//在实际工程中发现,其实设置一个即可
#define __EXPORT_CLASS_   __declspec(dllexport)

class __EXPORT_CLASS_ ExportData
{
public:
    ExportData();
    ~ExportData();
public:
    int GetData(int d);
private:
    int d_ = 0;
};

//ExportData.cpp
#include "stdafx.h"
#include "ExportData.h"

ExportData::ExportData()
{
}
ExportData::~ExportData()
{
}
int ExportData::GetData(int d)
{
    this->d_ = d;
    return  this->d_ + d;
}

//test.cpp
#include "stdafx.h"
 //注意下面两行调用,目的是为了将库的函数从导出设置为导入
#define MYDLL_EXPORTS
#define __EXPORT_CLASS_
#include "../DllPro/DllPro.h"
#include "../DllPro/ExportData.h"
#include 

//可以在此处如此调用,也可以在VS中设置库的依赖路径
#pragma comment(lib,"../Debug/DllPro.lib")
int main(){
    int ret = Sum(10,100);
    std::cout <"sum is:" <std::endl;
    ret = Mul(10,100);
    std::cout <"mul is:" <std::endl;

    ExportData data;
    ret = data.GetData(ret);
    std::cout <"getdata is:" <std::endl;
    return 0;
}

上面的代码分三部分,DllPro部分为API函数直接导出,ExportData为类导出,test部分为应用测试。当然,API的导出也可以使用def文件,这样更清楚:

LIBRARY dllpro
EXPORTS
Sum @ 1
Mul @ 2

这个导出文件很简单,直接在VS中新建立就可以,内容不用介绍,直接看上面的名字就可以,既提供了按名称访问也提供了按索引访问。上面的程序直接编译即可使用,注意,是X32,目的是为了讲解相关的库的导入导出约定。

三、动态库的分析工具

在Windows下的库分析工具那是相当多。为啥?得拜病毒太多所赐。自流氓大佬反水后,基本病毒和流氓软件在PC端的传播被扼制住了。另外搞这些软件开发的人也纷纷出于经济或者自身安全等缘由都上岸成立了安全公司,所以明显的库的分析工具不如十年前春笋般的出现了,即使有,也是收费的。不过,这些工具仍然还可以使用,如果仅仅是开发使用程序,这些工具都绰绰有余。
1、自带的命令:dumpbin
常用的参数:
/ALL:         除代码反汇编外的所有可用信息。
/DEPENDENTS:  查看应用依赖项,特别是对DLL的依赖很有用
/EXPORTS:         查看可执行文件或dll中导出的符号定义,这个用来查看调用时的导出函数名
/IMPORTS[:file]:  查看指定DLL的导入相关
/OUTFILE:filename: 输出相关到指定文件

659f1782cb6cc80d435c55ce294f084e.png

2、常用Depends
这个非常简单,直接把相关的可文件拖到工具上即可:

1cb80b25e53dea7c7c775e103a8f6c85.png

3、其它工具如IDA,
静态的有IDAPRO,动态的有Ollydbg、Windbg,这些工具是用来作逆向的,用来作库分析那肯定是杠杠的。使用的方法这里就不做介绍了,有兴趣去看雪网站学习就可以了。

四、动态库的管理

动态库的管理从原则上要遵守以下几点:
1、库的版本管理要严格,从平台到命名到相同库的升级命名,依赖命名等,这是DLL HELL的根源。
2、严格管理动态库和静态库的混合使用,除非必要,不要混用。
3、要有严格的说明文档并尽量有专人维护。
4、源码可追溯。
如果做到上面几点,对于中小规模的应用,应该是没有什么大问题了。

五、总结

Windows的动态库的优点在于有Vistual Studio这一大杀器存在,而导致开发上很简单,至少对于初学者来说不用面对复杂的命令,按照网上或者书的资料,几下就搞一个例程出来。但是简单往往是表象,内里的复杂性往往让一些老程序员都崩溃,特别是遇到一些集成公司,应用的库千奇百怪,这就需要工程构建者的细心和耐心了。
总而言之一句话,Windows看上去很美,但美是需要代价的。

150c4ecc514b340bd020492c90de3553.png

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值