当前位置:C++技术网 > 资讯 > 大话dll导出函数与dll封装的关系的思想原理

大话dll导出函数与dll封装的关系的思想原理

更新时间:2016-03-22 22:14:36浏览次数:1+次

    我们导出的函数到底有什么用呢?是不是我们所有的功能都用函数导出来呢?dll有什么用?如果要在dll中实现窗口或者其他更多的功能,是不是都要用函数一个个导出呢?
    这些问题基本上是开始涉足dll封装导出函数的人想到的疑问。这些问题我不会一个个跟你说,我会告诉一个整体而且是引导性的解释。不要说这是偷懒,恰恰相反,当我把这种模式套路告诉你,会让你真正进入另一番境界,而不是纠结于具体的一些语法。基本语法网上一查一大把的,然而这样的引导性启发性的文章,基本上是凤毛菱角。很多文章看似很全面,讲的也挺好,但是只会增加学习者的负担。当我在看一些文章解释一些新技术的时候,如果列举了很多很多的技术点,我会想,这么多东西我能够掌握吗?很多时候,一些人也是因为这些全面庞大而又繁杂的技术知识罗列吓到,然后放弃继续钻研了。
    大道至简!我始终坚信这一个道理,所以在看似很复杂的技术里,我总是想找到一个至高点,让我看了对这个技术体系一览无余,让我学到哪,该学什么都一清二楚,才不会越学越糊涂。
    大道至简!只有掌握了大道,纵观了全局,然后再细化学习,才不会云里雾里,才会学的更加清晰明白,使用技术也就更加灵活。

    我先用一个图来解释导出函数和dll内部封装的东西的关系吧:

导出函数与dll的关系原理图

【导出函数与dll的关系原理图】
    当你看到这个图时,可能你还没有看懂,可能你会很震撼,可能你会觉得不可思议。
    实际上,导出函数只是作为dll对外的一个接口,你调用导出函数,就会引起dll内部的一阵涌动。然后最后将结果通过导出函数返回给你。不知道你有没有想过一个问题,为什么我们调用CreateWindow函数就可以创建一个很不错的窗口,而且窗口还有各种基本功能了。你可能一脸茫然!我们的API函数也就是导出函数呀。Windows系统给我们提供了API函数,也就是给我提供了一个与系统内部交互的接口而已。所谓的API,就是应用程序接口,我们写的程序时应用程序,那么接口也就是API函数,我们调用API函数就可以完成很多功能,而我们实际上就简单调用了一些API函数而已。
    我们调用了API函数,实际上就是将我们的需求通过API函数告诉系统了,系统提供了大量的Dll来支持我们的需要。每一个dll里面都集成了各种强大的功能支持。可以说,Windows就是一个强大的UI引擎。当然其他方面也都是。
    你可能会问,dll到底能干嘛?我可以告诉你,dll可以做你想做的任何事情。dll也是可以和普通程序一样的,只是它不是单独执行的个体,需要寄生到其他进程运行,一旦他运行起来,和普通程序没有任何区别。
    然而你可能还是不太清楚这些引擎、这些窗口界面。。。都是怎么实现的,对吧。当你调用一个导出函数时,也就开启了一个浩瀚的宇宙。如果这个dll是一个游戏引擎,那将会有各种核心的程序功能,你只需要简单的组织程序的逻辑,游戏的物理碰撞检测,绚丽的界面什么的,dll里都已经提供了。如果你想计算宇宙大爆炸的可能性,刚好得到的dll就可以实现这种计算,而导出的函数就是一个无参数的函数,你只需要调用这个函数就可以执行计算,最后将结果显示出来。此时你只是调用了dll导出来的API接口函数而已,你并没有掌握宇宙大爆炸的计算,也没有掌握游戏引擎的开发,只是会调用API函数而已。哪些牛叉的功能都是在dll里完成的。
    我想,说了这么多,你对于dll和导出函数有一定的印象了。为了加强你的认识,我结合伪代码来给大家讲解一下。
    我想在dll里用一个C++类实现Windows窗口的创建,然后利用窗口可以做我们知道的各种事情。不过,我们将这些功能包括界面都封装在dll里,然后提供给其他人使用,人家只要简单调用show就可以将这个复杂的窗口程序启动,再调用一个函数就可以让这个窗口关闭和销毁。而调用的这些函数就是我们dll提供的API函数了。调用API的程序员不需要知道界面是如何做出来的,也不用知道窗口上的各种功能如何做的,他只需要知道调用dll提供的API函数即可。
    封装dll的创建项目等过程我就不在这里说了,大家可以上网查一下。我描述性写一下dll里的一个类。

下面是dll里的代码:
class  universe_cjjjs
{
public:
    universe_cjjjs();
    ~universe_cjjjs();
    long long GetAtomTime(){.....}
    long long GetAtomSize(){.....}
    .....
    void ShowResult();
}
extern "C" __declspec( dllexport ) long long CaculateUniverseKinds()
{
     universe_cjjjs uc;
     uc.GetAtomTime();
     uc.GetAtomSize();
     .....
     ShowResult();
}

    dll里面的类和导出函数,导出函数为全局函数,使用了【extern "C" __declspec( dllexport )】以C语言形式导出函数。我们的dll只提供一个导出函数,我们执行这个导出函数就可以开始计算宇宙大爆炸可能形成的宇宙类型种数。
    那么在dll提供的头文件中,也就一个导出函数的声明,计算宇宙的类我们看不到。在调用dll的函数时,我们是看不到类的任何信息的,我们只知道这个导出函数。那么我们就可以在函数中这样调用dll提供的API函数了:
//包含dll提供的头文件
#include <iostream>
using namespace std;
void main()
{
    long long kinds = CaculateUniverseKinds();
    cout<<"模拟计算得到宇宙大爆炸产生的宇宙类型数为:"<<kinds<<endl;
}

    那么到此,我演示完了一个dll的代码结构和调用dll提供的导出函数的样子。可以说,我们不需要任何宇宙的知识,也可以计算宇宙哦。
    如果是C/C++程序,可以包含头文件或者直接动态调用dll里的函数执行,而C#这些语言,也就只要直接调用dll的函数了。因为他们并不像C/C++一样用头文件,不过动态加载dll的函数都是一样的。在跨语言调用dll时,也就使用动态加载dll调用函数就好了。
    所以说到这里,我想你应该很清楚dll封装和导出函数这个概念了。这是一个思想模式,当你有这个模式之后,你再查询资料学习时,也就始终有一个大局了。自己再多思考,结合自己的经验,慢慢积累经验,悟性也就会越来越高,自然学起来也就越来越轻松了。