lib文件和dll文件的区别_dll2lib

lib文件和dll文件的区别_dll2lib一.简介1.1C++两种库文件lib包含了函数所在的dll文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的dll提供,称为动态链接库dynamiclinklibrary。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一. 简介

1.1 C++两种库文件

  1. lib包含了函数所在的dll文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的dll提供,称为动态链接库dynamic link library。(这种方式更灵活,写的程序体积小,但是需要.exe和dll同时发布)
  2. lib包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library。(这种方式不是很灵活,因为lib被编译到.exe中,写出的程序体积大,但是只需要发布exe即可,不需要dll文件)

1.2 C++两种链接方式

  1. 动态链接使用动态链接库,允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位 dll 函数的可执行代码所需的信息。
  2. 静态链接使用静态链接库,链接器从静态链接库 lib 获取所有被引用函数,并将库同代码一起放到可执行文件中。

1.3 lib与dll的区别

1. 功能区别

  • lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
  • 如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
  • 动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。

2. 文件数量的区别

  1. (静态连接)使用lib需注意两个文件:
  • .h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
  • .LIB文件,略。
  1. (动态连接)使用dll需注意三个文件:
  • .h头文件,包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中。
  • .LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用程序,否则产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32API函数LoadLibrary、GetProcAddress装载。
  • .dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。

二. lib文件

2.1 生成工具

操作系统: Win7

开发软件: VS2010

2.2 生成步骤

  1. 建立win32控制台工程MyLib(或者win32项目中下的静态库), 添加mySub.h文件以及mySub.cpp文件。

  2. 编写mySub.h文件代码

    #ifndef _MYSUB_H               // 这里的#ifndef可以避免头文件重复包含
    #define _MYSUB_H  
    void mySub(int a,int b);       // 这一行代码不能够写在上一行,只能另起一行写
    #endif

  3. 编写mySub.cpp文件代码

    1   #include "mySub.h"                   //包含头文件
    2   #include <iostream>                  
    3                                    
    4   void mySub(int a,int b)              //自定义的函数 
    5   {
    6      std::cout<<(a-b)<<std::endl;
    7   }

  4. 由于在工程中,没有main()函数,所以编译可能会出错。这时,点击工程,并选择工程属性,出现下图,选择静态链接库即可。

     
    lib文件和dll文件的区别_dll2lib

  1. 这时候再按快捷键 F7,build solution即可产生lib文件。在Debug中只生成.lib文件。

2.3 lib文件的使用

  1. 新建一个.cpp文件myLibTest.cpp(用于测试)

     1 #include <iostream>
     2 #include "mySub.h"                       // 引用头文件
     3 using namespace std;
     4 
     5 #pragma comment(lib,"MyLib.lib")         // 导入上一步生成的lib文件
     6 
     7 int main()
     8 {
     9   mySub(5,4);                            // 调用lib中的自定义函数mySub()
    10 
    11   return 0;
    12 }

  2. 点击工程,并选择工程属性,出现下图,将附加库目录新增包含刚才生成.lib的目录。

     
    lib文件和dll文件的区别_dll2lib

    012303.png

  1. 将工程项目属性中的配置类型改回至原来默认的应用程序(.exe),并执行myLibTest.cpp。

三. dll文件

3.1 生成.dll文件

  1. 新建win32项目,项目名称为SubDLL,解决方案名称为DLLTest,下一步。

  2. 选择应用程序类型为DLL,将附加选项的“导出符号”勾选上,完成。

  3. 修改SubDLL.h中的内容(将原来代码中,除预处理部分的代码外全部删除),并在后面新增你要实现的函数声明(见代码第21行)。注意:项目名为SubDLL,但此时生成的名字为 SUBDLL。

    #ifdef SUBDLL_EXPORTS
    #define SUBDLL_API __declspec(dllexport)
    #else
    #define SUBDLL_API __declspec(dllimport)
    #endif
    
    /*
    // 此类是从 SubDLL.dll 导出的
    class SUBDLL_API CSubDLL {
    public:
     CSubDLL(void);
     // TODO: 在此添加您的方法。
    };
    
    extern SUBDLL_API int nSubDLL;
    
    SUBDLL_API int fnSubDLL(void);
    */
    
    //这边是新增的内容
    SUBDLL_API void mySub(); 

  4. 修改SubDLL.cpp中的内容(将原来代码中,除头文件引入部分的代码外全部删除),并在后面新增你要实现的函数声明(见代码第26行)。

    // SubDLL.cpp : 定义 DLL 应用程序的导出函数。
    //
    
    #include "stdafx.h"
    #include "SubDLL.h"
    
    #include<stdio.h>
    /*
    // 这是导出变量的一个示例
    SUBDLL_API int nSubDLL=0;
    
    // 这是导出函数的一个示例。
    SUBDLL_API int fnSubDLL(void)
    {
     return 42;
    }
    
    // 这是已导出类的构造函数。
    // 有关类定义的信息,请参阅 SubDLL.h
    CSubDLL::CSubDLL()
    {
     return;
    }
    */
    //这边为SUM()的内容,很简易
    SUBDLL_API void mySub(int a,int b)
    {
     printf("the result is %d",a-b);
    }

  5. 点击“项目”,选择“属性”,进行如下图的配置(粗体字显示部分)。

     
    lib文件和dll文件的区别_dll2lib

    012306.png

  1. 构建项目(build)/生成解决方案,在项目的debug目录下面会生成很多的文件,其中包括有.dll和.lib。

3.2 dll文件的使用

3.2.1 显示调用方式

  1. 在之前“解决方案”中新建项目(选中解决方案 -> 增加 -> 新建项目),这次选择“win32控制台应用程序”,生成向导中选择“空项目”即可。取名为MyTest。

  2. 在新建项目的源文件下新建一个UseDLL.cpp文件,下面是其中的代码。

    #include <iostream>
    #include <Windows.h>          //使用函数和某些特殊变量
    
    using namespace std;
    typedef void (*FUN)(int,int); //定义一个函数指针,确定调用函数的形参
    
    int main()
    {
     const char* dllname = "SUBDLL.dll"; // 加载.dll
     const char* funname = "mySub";      //SUMDLL.cpp中函数名称
    
     HMODULE hDLL = LoadLibrary(dllname); //不要问,跟着做
    
     if (hDLL != NULL)
     {
         FUN fp = FUN(GetProcAddress(hDLL,funname)); //继续做,不要问
         if(fp != NULL)
            {
              fp(5,4);
            }
         else 
            {
              cout << "Can not Find: " << funname << endl;
            }    
         FreeLibrary(hDLL);
     }
     else 
         cout << "Can not find: " << dllname;
      
     return 0;
    }

  3. 点击解决方案名,选择设置启动项目 -> 通用属性 -> 启动项目 -> 单启动项目(选中UseDLL)。

  4. 运行项目,出现了错误:Can not find:mySub。造成这种错误的原因正是导出函数的修饰名称。在dll二进制文件中,经过编译器的“加工”,实际上有了不同的名称。这也是函数重载机制得以实现的一个技术支持。怎么办呢?我们可以通过vs2010附带工具dumpbin,找到加工以后的名称。详见dumpbin工具的使用

    • 在C:\Program Files(x86)\Microsoft Visual Studio 10.0\VC\bin目录下,按住shift键,鼠标右键在空白处单击,选择在此处打开命令窗口
    • 输入命令: dumpbin /export 文件全名
    • 将“加工”后的真是函数名复制后,粘贴。赋值给UseDLL.cpp文件中的变量funname。
    • 经过上一步后,重新执行UseDLL.cpp,成功运行。详见VS2010 C++ 调用 DLL (C++编写)
  5. 为了能够使原来的UseDLL.cpp(上面第2步所示代码)成功运行,可以进行下列操作:

    • 生成DLL文件的SubDLL项目的源文件中新建模块定义文件createDLL.def,其中的代码如下:

      LIBRARY createDLL  
      EXPORTS  
      mySub = ?mySub@@YAXHH@Z          //?mySub@@YAXHH@Z 即为dumpbin工具找到的真实名。

    • 修改SubDLL.h中的代码(去掉这些不太规范的修饰名称),修改之后重新编译生成CreateDLL.dll。

      #ifdef SUBDLL_EXPORTS
      #define SUBDLL_API        //去掉了原来的 __declspec(dllexport) 
      #else              //或改为 #define SUBDLL_API  extern "C" __declspec(dllexport)
      #define  SUBDLL_API           //同上  
      #endif

  6. 重新运行UseDLL.cpp程序,成功执行。

3.2.2 隐式调用方式

  1. 在之前“解决方案”中新建项目(选中解决方案 -> 增加 -> 新建项目),这次选择“win32控制台应用程序”,生成向导中选择“空项目”即可。取名为MyTest。

  2. 在新建项目的源文件下新建一个UseDLL.cpp文件,下面是其中的代码。

    #include <iostream>
    
    extern void mySub(int,int);
    
    int main()
    {
     mySub(5,4);
     return 0;
    }

  3. 右键工程–>Linker–>General–>Additional Library Directories(附加库目录) –>找到那个SubDLL.lib所在的目录

  4. 右键UseDLL工程–>Linker->input写下lib的名称。如SubDLL.lib和你DEBUG文件下的对应(这步没有也可以,因为会在上一步的路径下寻找)。

  5. 点击解决方案名,选择设置启动项目 -> 通用属性 -> 启动项目 -> 单启动项目(选中UseDLL)

  6. 运行UseDLL.cpp程序,成功执行。

参考资料

四. 小结

4.1 程序中的问题

  1. error C2664: “LoadLibraryW”: 不能将参数 1 从“const char [10]”转换为“LPCWSTR”与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
    解决方法:

    选中项目,然后点击属性——>配置属性——>常规——>项目默认值——>字符集,选为“使用多字节字符集”

     
    lib文件和dll文件的区别_dll2lib

    012304.png

  1. fatal error LNK1104: 无法打开文件:×××.lib的解决办法
    一般情况是因为没有导入相应的.lib文件,或者是导入的路径有误。给项目添加库文件路径。

    在VS中右击项目点属性:

    配置属性–>链接器–>常规–>附加目录 。在里面填上库文件所在的路径即可。

  2. fatal error LNK1104: 无法打开文件“x x x.def”
    如果不想使用xxx.def文件,可以在项目-属性-配置属性-链接器-输入 选项中,将右侧的模块定义文件删掉,这样就不会提示了。

4.2 vs的常用操作

  1. 添加头文件:

    配置属性–>C/C++–>常规–>附加包含目录 加上头文件存放的目录。

  2. 添加lib文件:

    • 配置属性–>链接器–>输入–>附加依赖项加入库名(×××.lib);或者是在cpp源文件中用#pragma comment(lib,”×××.lib”)来代替。
    • 将xxx.lib拷入工程所在目录,或者执行文件生成的目录,或者系统Lib目录中(如果lib文件是自己生成的,可以跳过这一步)。
    • 给项目添加库文件路径:
      在VS中右击项目点属性。配置属性–>链接器–>常规–>附加目录 。在里面填上库文件所在的路径即可。

4.3 windows小常识

    1. 在当前目录下运行命令:shift键 + 鼠标右键

    2. 首先将命令窗体属性中的快速编辑模式选中打勾,这样就可以一复制粘贴了。复制dos窗体中的内容:右键->标记->选择复制内容->回车键或者鼠标右击,粘贴的时候:鼠标右键粘贴。
      dos中不能使用快捷键。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/167993.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • @RequestParam注解详解

    @RequestParam注解详解@RequestParam是传递参数的.@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。publicStringqueryUserName(@RequestParamStringuserName)在url中输入:localhost:8080/**/?userName=zhangsan请求中包含username参数(如/requestparam1?userName=…

    2022年10月28日
  • Java finalize方法使用

    Java finalize方法使用《JAVA编程思想》:java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。         (1).对象不一定会被回收。      (2).垃圾回收不是析构函数。      (3).垃圾回收只与内存有关。

  • xshell的安装和使用_git详细教程

    xshell的安装和使用_git详细教程1、Xshell6的安装废话不多说直接上链接:链接:https://pan.baidu.com/s/1WCOxkdhLIZj7yLakWu4Tdw提取码:t3ak2、了解Xshell及其使用2.1、Xshell是什么东西?首先我们要知道Xshell是用来干什么的。Xshell其实就是一个远程终端工具,它可以将你的个人pc(个人电脑)和你在远端的机器连接起来,通过向Xshell输入命令然后他通过网络将命令传送给远端Linux机器然后远端的Linux机器将其运行结果通过网络传回个人电脑。.

  • 数学建模13种常见方法

    数学建模13种常见方法下面来介绍一下数学建模大赛中常用的13中建模方法:1、层次分析法,简称AHP,是指将与决策总是有关的元素分解成目标、准则、方案等层次,在此基础之上进行定性和定量分析的决策方法。该方法是美国运筹学家匹茨堡大学教授萨蒂于20世纪70年代初,在为美国国防部研究"根据各个工业部门对国家福利的贡献大小而进行电力分配"课题时,应用网络系统理论和多目标综合评价方法,提出的一种层次权重决策分析方法。2、多…

  • 解决EXSi6.0没有WEB Client的问题

    解决EXSi6.0没有WEB Client的问题问题:安装好EXSi之后通过web访问,只有vSphere下载,没有openwebclient经过百度之后发现EXSi6.0不支持Web,但是支持安装Web,这就好办了。动手!!!思路:1、下载esxui-signed-7119706.vib2、通过SecureCRT连接EXSi服务器3、开启sftp连接4、转到EXSi的/tmp目录,这里仅仅是习惯,其他目录…

  • scratch编程一款节奏小游戏「建议收藏」

    scratch编程一款节奏小游戏「建议收藏」今天小恐龙来教大家做一款好玩的小游戏:这个游戏本恐龙没有加音乐,因为箭头落下的速度会根据我们的命中率来改变,按中的越多速度就越快,漏的越多速度就越慢,有上下限!首先画出轨道,粗细随意:轨道直接设置成移到(0,0)就可以了,没有别的程序然后是箭头:变量分值和速度是隐藏起来的,我们在玩的时候是看不到的,速度下限是5,上限是10,不然太快了反应不过来!箭头克隆体程序:最后是判定线的程序:如果是觉得没有音乐太单调的话,可以通过创建一个链表来储存音符。再新建一个变量,每按中一个箭头就将

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号