zoukankan      html  css  js  c++  java
  • Win32编程之静态库编写与使用.动态链接库的编写与使用

              Win32编程之静态库编写与使用.动态链接库的编写与使用

    一丶什么是静态库.什么是动态链接库.

      静态库其实就是解决模块开发的一种解决方案.在以前.我们写代码的时候.每个人都可以独立写一个项目.但是现在不行了.一个项目往往要很多人一起去编写.而其中用到的技术就类似于静态库.

    每个人编写自己的东西.最后组合.

      动态链接库.也称为Dll. 为什么有了静态库还要有动态链接库. 原因是静态库优缺点的.所以才出了动态链接库补充这个缺点.

    缺点:

      1.代码体积大. 使用静态库的程序编译出的体积很大.在汇编的层次中就是把静态库的代码跟可执行文件相链接了.

      2.重复代码多.一个静态库可以有很多人编写.有得函数会有多次编写.

    动态链接库就是解决上面缺点的.

    二丶如何编写静态库以及如何使用.

    1.创建静态库或者lib步骤

       如果是VS系列编译器. 创建静态库的方法. VC++6.0 创建的时候是一个 static lib.... 因为笔者Vc6.0没有安装成功.(确实不支持了) 所以不再累赘

      新建项目 -> VC++ ->win32项目 -> 静态库.

    我们可以选择生成dll还是静态库.

    2.编写静态lib库

      如果我们创建了一个库文件.那么很简单. 添加一个.h文件. 填加一个实现文件. 

    也就是一个.h 一个.cpp

      .h放我们的函数声明.

      .cpp放我们的函数实现即可.

    例如下图:

    添加一个加法函数.

    .h方声明. .cpp实现.

    .h中的声明

      

    int RetMyAddNumber(int a, int b);

    .cpp的实现.

      

    int RetMyAddNumber(int a,int b)
    {
        return a + b;
    }

    直接编译.然后寻找目录下我们编译好的静态lib库即可.

     3.使用静态lib库

      使用我们的静态lib库很简单.

      1.需要.h文件. 也就是我们编写静态lib的声明文件.

      2.需要编译好的静态lib.

      3.我们的程序包含.h声明文件.并且再次使用宏命令包含静态lib.文件  #pragam comment(lib,"xxxx.lib");

    这个是第一种方法.

    第二种方法是放到目录中.并且VS配置库目录即可. 跟使用C语言的lib库是一样的.具体怎么配置不再累赘. 比较常用第一种.

    三丶编写Dll并且使用DLL

      生成我们的DLL跟上面是一样的.主不过选择DLL即可.

     编写DLL 我们也需要有个头文件.跟一个实现文件.因为要给别人使用.

    .h声明文件导出我们的Dll

     1.第一种关键字导出方法. 

    extern "C" _declspec(dllexport) int _stdcall RetMyAddNumber(int a, int b);
    
    extern "C" _declspec(dllexport) int _stdcall RetMySubNumber(int a, int b);

    .cpp实现文件

      

    #include "MyDllHead.h"  //必须包含.不包含则不会导出.
    int
    RetMyAddNumber(int a, int b) { return a + b; } int RetMySubNumber(int a, int b) { return a - b; }

    注意,因为我们的函数要给别人使用.所以必须要导出. 这里有两种方法. 第一种就是关键字导出. 第二种就是.def导出.

    关键字导出:

      _declspec(dllexeport)  函数返回值  函数调用约定 函数名称 (参数列表)  这样导出的函数带有名称粉碎.也就是说我们要使用的时候.函数名字已经变了.

    所以另一个关键字 extern "C" 这个意思就是按照C语言函数定义给我们导出. 名称粉碎是因为C++有函数重载的概念.所以函数重载其实本质就是名字不一样了而已.C语言没有.所以按照C语言导出.

    如果熟悉PE的应该知道导出函数的时候都有一个导出表.而这个导出表则存储着DLL导出的函数.

    PS: 调用约定不同.导出函数的函数名就不同. 如果我们以C调用约定风格导出的话.那么函数名就不会重命名.

    例如:

      

    导出函数代码.

      

    extern "C" __declspec(dllexport) int _cdecl RetMyAddNumber(int a, int b)
    {
        return a + b;
    }
    
    extern "C" __declspec(dllexport) int _cdecl RetMySubNumber(int a, int b)
    {
        return a - b;
    }
    直接在函数定义的时候顺便导出了.也可以在函数声明上导出.如果给别人使用.并且是隐式调用的话.需要给.h声明文件.

      2.第二种方式 .def文件导出

    def文件导出很方便.

    首先要创建一个.def文件在自己的工程中.

    按照语法导出.

    语法:

      

    EXPORTS
            函数名 @编号
            函数名 @编号 NONAME

    函数名就是导出的时候函数名.编号的话就是导出的时候可以有编号.

    编号的作用: 有得时候如果动态调用DLL. (loadlibrary + GetProcAddress)那么我们可以直接GetProcAddress(DLL句柄, (LPCSTR)编号) 这样来调用我们的DLL

    使用Def文件导出上图我们编写的两个函数.

    LIBRARY 说的是要指明我们导出的DLL的名字. 我们的名字就是DLL 所以就给了.

    EXPORTS就是导出函数.

        我们要导出的函数只有一个 RetMyAddNumber @ 1. 这个函数的编号就是1. 所以我们Get的使用使用编号调用也好. 名字调用也好.

     PS: 注意一下.如果我们使用.def文件导出. 那么就不能使用Extern "C" 这个名字了.也不要使用关键字了.

     

    3.使用DLL

      使用DLL有两种方式.第一种就是显式调用.另一种则是隐式调用

    1.显示调用

      显示调用很简单.  

      1.定义函数指针.

      2.使用LoadLibrary加载DLL,返回DLL句柄

      3.使用GetProcAddress(dll句柄,你要获取的函数名或者编号)

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    #pragma comment(lib,"staticlib.lib")
    typedef int (*_cdecl PFN)(int, int); //定义函数指针.要使用DLL
    
    int main()
    {
        //使用导出的全局变量
        
        HMODULE hdll = LoadLibrary(TEXT("Dll.dll"));
        PFN pAdd = (PFN)GetProcAddress(hdll, "RetMyAddNumber");
        int nValue = pAdd(100, 11);
    
    
        printf("nValue = %d 
     ", nValue);
        getchar();
        return 0;
    }

    2.隐式调用

      隐示调用就很简单了.在生成DLL的时候.会对应生成lib. 我们直接使用这个lib即可. 跟上图使用静态lib库一样. 但是需要注意我们也需要DLL

    这个lib库只是辅助信息.并不跟上面你的静态库lib一样.上面的静态库lib里面是有实质性的代码的.

    例如以下伪代码:

      

    #inclue "xxx头"
    
    #pragma comment(lib,"dll的lib")
    
    __declspec(dllimport) int MyAdd(int a,int b);  引入声明即可.如果我们的头文件引入了
    则不用写.

    PS: 静态lib库的代码使用的时候会跟exe链接在一起. 在汇编程序中看 就是 Call 地址.  而 dll库则是 Call [地址] 间接调用.

    真正用到的时候才会把地址填写.

  • 相关阅读:
    CSS3 探索发现系列:一组梦幻般的 CSS3 动画按钮效果
    JS日历控件集合附效果图、源代码
    uml 类图聚合与组合
    统计 按年,月,季度
    Visual studio 2008快捷键大全 (转)
    SQL常用语句和函数(转)
    C#函数传参的out与ref的应用(转)
    Session.Abandon和Session.Clear有何不同 (转)
    .net C#:String.Format数字格式化输出 (转)
    〈转贴〉如何解决 Windows XP 中的硬件和软件驱动程序问题
  • 原文地址:https://www.cnblogs.com/iBinary/p/9594256.html
Copyright © 2011-2022 走看看